Update packages version
Add first test Add design pattern builder + Youtube builder
This commit is contained in:
parent
bf55adf8da
commit
f1b1e23792
778
package-lock.json
generated
778
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
|
@ -16,14 +16,15 @@
|
|||
"discord.js": "^12.0.1",
|
||||
"fs-extra": "^9.0.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
"lodash": "^4.17.15",
|
||||
"pm2": "^4.2.3",
|
||||
"lodash": "^4.17.20",
|
||||
"pm2": "^4.5.1",
|
||||
"rss-parser": "^3.7.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"chai": "^4.2.0",
|
||||
"mocha": "^8.2.1",
|
||||
"proxyquire": "^2.1.3",
|
||||
"sinon": "^9.2.2"
|
||||
"sinon": "^9.2.2",
|
||||
"sinon-chai": "^3.5.0"
|
||||
}
|
||||
}
|
||||
|
|
47
src/Models/Builders/AbstractListenerRSSBuilder.js
Normal file
47
src/Models/Builders/AbstractListenerRSSBuilder.js
Normal file
|
@ -0,0 +1,47 @@
|
|||
const ListenerRSS = require('../listener-rss');
|
||||
|
||||
class AbstractListnerRSSBuilder {
|
||||
_listenerRSS = undefined;
|
||||
|
||||
constructor() {
|
||||
if(this.constructor === AbstractListnerRSSBuilder)
|
||||
throw new Error('The Abstract class "AbstractListnerRSSBuilder" cannot be instantiated');
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief first function to call after constructor. It's building the listener
|
||||
* @param infos Must to be an object ListenerRSSInfos
|
||||
*/
|
||||
constructListener(infos) {
|
||||
this._listenerRSS = new ListenerRSS();
|
||||
|
||||
this.setInfos(infos);
|
||||
this.setSpecificInfos();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief give the listener just build
|
||||
* @return ListenerRSS with all the setups datas
|
||||
* @exception if the listener isn't construct
|
||||
*/
|
||||
get listenerRSS() {
|
||||
if(this._listenerRSS === undefined)
|
||||
throw new Error('the listener is not yet build');
|
||||
return this._listenerRSS;
|
||||
}
|
||||
|
||||
setInfos(infos) { // Nominal Infos (like name, addresse, and other)
|
||||
this._listenerRSS.name = infos._name;
|
||||
this._listenerRSS.address = infos._address;
|
||||
this._listenerRSS.timeloop = infos._timeloop;
|
||||
this._listenerRSS.name = infos._name;
|
||||
}
|
||||
|
||||
setSpecificInfos() { // More generic infos who's depend of platforms
|
||||
throw new Error('This function is not implemented');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
module.exports = AbstractListnerRSSBuilder
|
16
src/Models/Builders/YoutubeListenerRSSBuilder.js
Normal file
16
src/Models/Builders/YoutubeListenerRSSBuilder.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
const AbstractListenerRSSBuilder = require('AbstractListenerRSSBuilder')
|
||||
|
||||
class YoutubeListenerRSSBuilder extends AbstractListenerRSSBuilder {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
setSpecificInfos() {
|
||||
this.listenerRSS._customfields = [
|
||||
['description', ['media:group', 'media:description']],
|
||||
['icon', ['media:group', 'media:thumbnail']]
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = YoutubeListenerRSSBuilder
|
42
src/Models/listenerRSSInfos.js
Normal file
42
src/Models/listenerRSSInfos.js
Normal file
|
@ -0,0 +1,42 @@
|
|||
class ListenerRSSInfos {
|
||||
_name = undefined; // name of the listener
|
||||
_address = undefined; // feed's address
|
||||
_timeloop = 1 * 60; // update time RSS feed
|
||||
_customfields = [] // rss fields custom
|
||||
|
||||
|
||||
|
||||
set name(value) {
|
||||
this._name = value;
|
||||
}
|
||||
|
||||
set address(value) {
|
||||
this._address = value;
|
||||
}
|
||||
|
||||
set timeloop(value) {
|
||||
this._timeloop = value;
|
||||
}
|
||||
|
||||
set customfields(value) {
|
||||
this._customfields = value;
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
get address() {
|
||||
return this._address;
|
||||
}
|
||||
|
||||
get timeloop() {
|
||||
return this._timeloop;
|
||||
}
|
||||
|
||||
get customfields() {
|
||||
return this._customfields;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ListenerRSSInfos
|
22
src/listener-director.js
Normal file
22
src/listener-director.js
Normal file
|
@ -0,0 +1,22 @@
|
|||
const YoutubeListenerRSSBuilder = require('./Models/YoutubeListenerRSSBuilder');
|
||||
|
||||
class ListenerBuildDirector {
|
||||
_builder = undefined;
|
||||
|
||||
|
||||
constructor(builder) {
|
||||
this._builder = builder;
|
||||
}
|
||||
|
||||
getListener() {
|
||||
return this._builder.listenerRSS();
|
||||
}
|
||||
|
||||
build(infos) {
|
||||
if(infos === undefined)
|
||||
throw new Error('infos must be initialized');
|
||||
this._builder.constructListener(infos);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ListenerBuildDirector
|
61
src/listener-rss.js
Normal file
61
src/listener-rss.js
Normal file
|
@ -0,0 +1,61 @@
|
|||
const jsonFile = require('jsonfile');
|
||||
const Parser = require('rss-parser');
|
||||
|
||||
|
||||
class ListenerRss {
|
||||
name = undefined;
|
||||
address = undefined;
|
||||
timeloop = 5 * 60; // time in seconds
|
||||
customfields = [];
|
||||
|
||||
// private fields
|
||||
parser = null;
|
||||
obj = null;
|
||||
loopRunning = false;
|
||||
|
||||
constructor(info) {
|
||||
// set parser
|
||||
this.parser = new Parser({
|
||||
customFields : {
|
||||
item: info._customfields.map((elt) => {
|
||||
return Array.isArray(elt[1]) ? elt[1][0] : elt[1];
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
// Set data
|
||||
this.name = info._name === undefined ? info._address : info._name; // if name is undefined let's take the address
|
||||
this.address = info._address;
|
||||
this.timeloop = info._timeloop;
|
||||
this.customfields = info._customfields;
|
||||
}
|
||||
|
||||
fetchRSS() {
|
||||
return this.parser.parseURL(this.address)
|
||||
.catch((err) => { throw new Error('bad address or no access : ' + err);});
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief call the callback function each looptime
|
||||
* @param callback function who's going to be called with the latest get
|
||||
*/
|
||||
start(callback) {
|
||||
this.loopRunning = true;
|
||||
|
||||
(async () => {
|
||||
while(this.loopRunning === true) {
|
||||
callback(await this.fetchRSS());
|
||||
await new Promise(res => setTimeout(res, this.timeloop * 1000));
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief stop the async function
|
||||
*/
|
||||
stop() {
|
||||
this.loopRunning = false;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ListenerRss
|
|
@ -1,59 +1,100 @@
|
|||
const chai = require("chai");
|
||||
const sinon = require("sinon");
|
||||
const proxyquire = require("proxyquire");
|
||||
const sinon_chai = require("sinon-chai");
|
||||
chai.use(sinon_chai);
|
||||
const Parser = require("rss-parser");
|
||||
|
||||
const Listeners = require('../src/listener-rss')
|
||||
const ListenerRRSInfo = require('../src/Models/listenerRSSInfos')
|
||||
const YtbBuilder = require('../src/Models/YoutubeListenerRSSBuilder')
|
||||
const YtbDirector = require('../src/listener-director')
|
||||
|
||||
|
||||
const expect = chai.expect;
|
||||
|
||||
describe("RSS Youtube", function () {
|
||||
let rssYoutubeService;
|
||||
let timecode;
|
||||
let routage;
|
||||
let parseUrlStub;
|
||||
let mockedInput = {
|
||||
describe("test class RSS: jsonfile", function () {
|
||||
let myListener = undefined;
|
||||
|
||||
let infosListener = new ListenerRRSInfo();
|
||||
infosListener.name = 'my-test-service';
|
||||
infosListener.address = 'fake.rss.service';
|
||||
infosListener.timeloop = 15;
|
||||
|
||||
// parseURL tests
|
||||
let stubParser;
|
||||
|
||||
const mockedRSSOutput = {
|
||||
items: [
|
||||
{
|
||||
id: "::account",
|
||||
url:
|
||||
isoDate: Date.now().toISOString(),
|
||||
"media:group": {
|
||||
"media:description": [
|
||||
"my description"
|
||||
]
|
||||
}
|
||||
'title': 'my title 00',
|
||||
'media:group': {
|
||||
'media:description': 'my description 00',
|
||||
'media:thumbnail': [{$: {height: 360, width: 420, url: 'my_image00.jpg'}}],
|
||||
},
|
||||
'link': 'my_url_00.com',
|
||||
'pubDate': 'myDate00'
|
||||
},
|
||||
{
|
||||
'title': 'my title 01',
|
||||
'media:group' : {
|
||||
'media:description': 'my description 01',
|
||||
'media:thumbnail': [{$: { height: 360, width: 420, url: 'my_image01.jpg'}}],
|
||||
},
|
||||
'link': 'my_url_01.com',
|
||||
'pubDate': 'myDate01'
|
||||
},
|
||||
{
|
||||
'title': 'my title 02',
|
||||
'media:group' : {
|
||||
'media:description': 'my description 02',
|
||||
'media:thumbnail': [{$: { height: 360, width: 420, url: 'my_image02.jpg'}}],
|
||||
},
|
||||
'link': 'my_url_02.com',
|
||||
'pubDate': 'myDate02'
|
||||
},
|
||||
]
|
||||
};
|
||||
|
||||
beforeEach(function () {
|
||||
timecode = {
|
||||
"lastCheck": "2020-11-12T17:44:11.713Z",
|
||||
"MyUser": "2020-11-12T17:44:11.713Z"
|
||||
};
|
||||
routage = {
|
||||
log: sinon.stub(),
|
||||
send: sinon.stub()
|
||||
};
|
||||
// stubs
|
||||
stubParser = sinon.stub(Parser.prototype, 'parseURL')
|
||||
.withArgs(listenerInfo.address)
|
||||
.resolves(mockedRSSOutput);
|
||||
|
||||
parseUrlStub = sinon.stub(Parser.prototype, "parseURL")
|
||||
.callsFake((_, callback) => callback(null, "data"));
|
||||
|
||||
rssYoutubeService = proxyquire("../services/rss-youtube", {
|
||||
"../modules/routage": () => routage,
|
||||
"../db/rss-youtube.json": {
|
||||
config: {
|
||||
timeLoop: 5,
|
||||
urlFeeds: "https://www.youtube.com/feeds/videos.xml?channel_id=",
|
||||
sliceDescription: 142
|
||||
},
|
||||
feeds: {
|
||||
MyUser: "Some channel"
|
||||
},
|
||||
timecode
|
||||
}
|
||||
});
|
||||
});
|
||||
// constructor
|
||||
myListener = new Listeners();
|
||||
})
|
||||
|
||||
afterEach(function () {
|
||||
Parser.prototype.parseURL.reset();
|
||||
// restore stubs
|
||||
Parser.prototype.parseURL.restore();
|
||||
});
|
||||
|
||||
describe("Building Ytb listener", function () {
|
||||
it("The build without problems", function () {
|
||||
let builder = new YtbBuilder();
|
||||
let director = new YtbDirector(builder);
|
||||
director.build(infosListener);
|
||||
myListener = director.getListener();
|
||||
|
||||
// assertions
|
||||
expect(stubParser).to.have.been.calledOnce;
|
||||
expect(stubParser).to.have.been.calledWith(infosListener._address);
|
||||
expect(myListener.customFields).to.eql([
|
||||
['description', ['media:group', 'media:description']],
|
||||
['icon', ['media:group', 'media:thumbnail']]
|
||||
]);
|
||||
//TODO test les infos dans "myListener"
|
||||
});
|
||||
});
|
||||
|
||||
//Todo
|
||||
describe.skip("start", function () {
|
||||
it("Let's start the timer", function () {
|
||||
myListener.setDatas(listenerInfo);
|
||||
myListener.start();
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue
Block a user