implementation @database/sqlite + test addapted

This commit is contained in:
Amaury Joly 2021-04-11 19:31:40 +02:00
parent 533d71e85e
commit 3f2b00eccb
9 changed files with 2891 additions and 8590 deletions

10496
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -25,16 +25,17 @@
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-mocha": "8.0.0",
"eslint-plugin-prettier": "3.3.1",
"mocha": "8.2.1",
"mocha": "^8.2.1",
"nock": "^13.0.11",
"prettier": "2.2.1",
"sinon-chai": "^3.5.0",
"tmp-promise": "^3.0.2",
"ts-node": "9.1.1",
"ts-sinon": "2.0.1",
"typescript": "^4.1.3"
},
"dependencies": {
"listener-rss": "file:../listener-rss",
"sqlite3": "^5.0.2"
"@databases/sqlite": "^3.0.0",
"listener-rss": "file:../listener-rss"
}
}

View File

@ -1,11 +1,7 @@
import EventEmitter from "events";
import { ListenerRss, ListenerRSSInfos } from "listener-rss";
interface ManageListenerInfo {
timeloop?: number;
path?: string;
}
import { SqliteTools } from "./sqlite-tools";
/**
* Permit to manage a ListenerRSS array, data storage and event aggregation
@ -14,83 +10,48 @@ export class ManageListener extends EventEmitter {
listenerArray: ListenerRss[] = [];
looprunning: boolean = false;
// manage aggregation
timeloop?: number;
buffUpdates: any[] = [];
buffNewEntries: any[] = [];
sqliteDb: SqliteTools;
constructor(info?: ManageListenerInfo) {
constructor(path: string) {
super();
if (info) {
if (info.timeloop) {
this.timeloop = info.timeloop;
}
if (info.path) {
const fs = require("fs");
const tmp = fs.readFileSync(info.path);
const configs: ListenerRSSInfos[] = JSON.parse(tmp);
configs.forEach((config) => this.addNewListener(config));
}
}
this.sqliteDb = new SqliteTools(path);
}
async load() {
await this.sqliteDb.ensureTableExists();
const configs: ListenerRSSInfos[] = await this.sqliteDb.fetchAll();
configs.forEach((config) => {
const newListener = new ListenerRss(config);
this.listenerArray.push(newListener);
this.settingEvents(newListener);
});
}
settingEvents(newListener: ListenerRss): void {
if (this.timeloop !== undefined) {
newListener.on("update", (obj) => this.buffUpdates.push(obj));
newListener.on("newEntries", (obj) => this.buffNewEntries.push(obj));
// /!\ todo /!\ threat error with aggregation
// newListener.on("error", (err) => this.emit("error", err));
} else {
newListener.on("update", (obj) => this.emit("update", obj));
newListener.on("newEntries", (obj) => this.emit("newEntries", obj));
newListener.on("error", (err) => this.emit("error", err));
}
newListener.on("update", (obj) => this.emit("update", obj));
newListener.on("newEntries", (obj) => this.emit("newEntries", obj));
newListener.on("error", (err) => this.emit("error", err));
}
addNewListener(info: ListenerRSSInfos): void {
async addNewListener(info: ListenerRSSInfos) {
const newListener = new ListenerRss(info);
this.listenerArray.push(newListener);
this.settingEvents(newListener);
await this.sqliteDb.insertListener(newListener);
}
save(path: string): void {
if (path.endsWith(".json")) {
const fs = require("fs");
fs.writeFileSync(
path,
JSON.stringify(
this.listenerArray.map((listener) => listener.getProperty())
)
);
}
async save() {
await this.sqliteDb.updateAll(
this.listenerArray.map((listener) => listener.getProperty())
);
}
startAll(): void {
if (!this.looprunning) {
this.looprunning = true;
this.listenerArray.forEach((listener) => listener.start());
if (this.timeloop) {
const fun: () => void = async () => {
this.emit("update", this.buffUpdates);
if (this.buffNewEntries.length) {
console.log(this.buffNewEntries.length);
this.emit("newEntries", this.buffNewEntries);
}
this.buffUpdates = [];
this.buffNewEntries = [];
};
(async () => {
while (this.looprunning) {
await fun();
await new Promise((res) =>
setTimeout(res, this.timeloop ? this.timeloop * 1000 : 0)
);
}
})();
}
}
}

71
src/sqlite-tools.ts Normal file
View File

@ -0,0 +1,71 @@
import { ListenerRSSInfos } from "listener-rss";
import connect, { sql } from "@databases/sqlite";
export class SqliteTools {
path?: string;
constructor(path?: string) {
this.path = path;
}
async ensureTableExists() {
const db = connect(this.path);
let req = sql`CREATE TABLE IF NOT EXISTS listeners
(
address TEXT NOT NULL UNIQUE,
customfields TEXT DEFAULT '[]',
timeloop INTEGER DEFAULT 300,
last_entries_links TEXT DEFAULT '[]',
PRIMARY KEY (address),
CHECK(timeloop >= 0)
);`;
await db.query(req);
await db.dispose();
}
async fetchAll(): Promise<ListenerRSSInfos[]> {
const db = connect(this.path);
let req = sql`SELECT *
FROM listeners`;
const rows = await db.query(req);
await db.dispose();
return rows.map((row: any) => ({
address: row["address"],
customfields: JSON.parse(row["customfields"]),
timeloop: row["timeloop"],
lastEntriesLinks: JSON.parse(row["last_entries_links"]),
}));
}
async insertListener(listener: ListenerRSSInfos) {
const db = connect(this.path);
let req = sql`INSERT INTO listeners (address, timeloop, customfields, last_entries_links)
VALUES (${listener.address},
${listener.timeloop},
${JSON.stringify(listener.customfields)},
${JSON.stringify(listener.lastEntriesLinks)})`;
await db.query(req);
await db.dispose();
}
async updateAll(listeners: ListenerRSSInfos[]) {
const db = connect(this.path);
await db.tx(async (transaction) => {
for (const listener of listeners) {
let req = sql`UPDATE listeners
SET last_entries_links = ${JSON.stringify(
listener.lastEntriesLinks
)}
WHERE address = ${listener.address}`;
await transaction.query(req);
}
});
await db.dispose();
}
}

View File

@ -1,20 +0,0 @@
[
{
"address": "https://www.youtube.com/feeds/videos.xml?channel_id=UCOuIgj0CYCXCvjWywjDbauw",
"customfields": { "media:group": ["media:group"] },
"lastEntriesLinks": [],
"timeloop": 10
},
{
"address": "https://www.youtube.com/feeds/videos.xml?channel_id=UCh2YBKhYIy-_LtfCIn2Jycg",
"customfields": { "media:group": ["media:group"] },
"lastEntriesLinks": [],
"timeloop": 20
},
{
"address": "https://www.youtube.com/feeds/videos.xml?channel_id=UCY7klexd1qEqxgqYK6W7BVQ",
"customfields": { "media:group": ["media:group"] },
"lastEntriesLinks": [],
"timeloop": 30
}
]

Binary file not shown.

View File

@ -2,84 +2,48 @@
import { ListenerRss, ListenerRSSInfos } from "listener-rss";
// local lib
import { ManageListener } from "../";
import { ManageListener } from "../src/";
// Unit test
import path from "path";
import { join as joinPath } from "path";
import events from "events";
import nock from "nock";
import * as chai from "chai";
import sinon from "ts-sinon";
import sinonChai from "sinon-chai";
import { withFile } from "tmp-promise";
chai.use(sinonChai);
const expect = chai.expect;
describe("test class GestionListener", function () {
describe("test constructor", function () {
it("should create a new manageListener object without params", function () {
// when
const ml = new ManageListener();
// expect
expect(ml.listenerArray).to.be.empty;
});
it("should create a new manageListener object with a param file", function () {
// given
const tmp = require("./RessourcesTest/FakeRessources/save.json");
// when
const ml = new ManageListener({
path: "tests/RessourcesTest/FakeRessources/save.json",
});
// expect
expect(tmp).to.be.eql(ml.listenerArray.map((item) => item.getProperty()));
});
});
const dataWithHistory: ListenerRSSInfos[] = require("./RessourcesTest/RealRessources/save.json");
const dataWithoutHistory = dataWithHistory.map((data) => ({
...data,
lastEntriesLinks: [],
}));
describe("test class ManageListener", function () {
describe("test saving", function () {
beforeEach("Clean old files if exist", function () {
const fs = require("fs");
if (fs.existsSync("tests/RessourcesTest/FakeRessources/fake_save.json"))
fs.unlinkSync("tests/RessourcesTest/FakeRessources/fake_save.json");
});
it("should save the inserted objects", async function () {
await withFile(async ({ path }) => {
// given
const ml = new ManageListener(path);
await ml.load();
afterEach("Clean old files if exist", function () {
const fs = require("fs");
if (fs.existsSync("tests/RessourcesTest/FakeRessources/fake_save.json"))
fs.unlinkSync("tests/RessourcesTest/FakeRessources/fake_save.json");
});
for (const item of dataWithoutHistory) await ml.addNewListener(item);
it("should save the inserted objects", function (): void {
// given
const ml = new ManageListener();
let expectedObj: ListenerRss[] = [];
// when
ml.save();
const ml_bis = new ManageListener(path);
await ml_bis.load();
for (let i = 1; i < 10; i++) {
const generatedInfo = {
address: `fake.rss.service.${i}`,
customfields: {
"media:group": ["media:group"],
},
timeloop: i * 10,
};
expectedObj.push(new ListenerRss(generatedInfo));
ml.addNewListener(generatedInfo);
}
// when
ml.save("tests/RessourcesTest/FakeRessources/fake_save.json");
const tmp = require("./RessourcesTest/FakeRessources/save.json");
ml.save("tests/RessourcesTest/FakeRessources/fake_save.json");
ml.save("tests/RessourcesTest/FakeRessources/fake_save.json");
// expect
expect(expectedObj.map((item) => item.getProperty())).to.be.eql(tmp);
// expect
expect(
ml_bis.listenerArray.map((listener) => listener.getProperty())
).to.be.eql(dataWithoutHistory);
});
});
});
@ -93,366 +57,370 @@ describe("test class GestionListener", function () {
});
it("should call correctly the events (no aggregation)", async function () {
// given
const clock = sinon.useFakeTimers();
const ml = new ManageListener({
path: "tests/RessourcesTest/RealRessources/save_no_history.json",
await withFile(async ({ path }) => {
// given
const clock = sinon.useFakeTimers();
const ml = new ManageListener(path);
await ml.load();
for (const item of dataWithoutHistory) await ml.addNewListener(item);
const updateSpy = sinon.spy();
const newEntriesSpy = sinon.spy();
const tabChannelId = [
"UCOuIgj0CYCXCvjWywjDbauw",
"UCh2YBKhYIy-_LtfCIn2Jycg",
"UCY7klexd1qEqxgqYK6W7BVQ",
];
ml.on("update", updateSpy);
ml.on("newEntries", newEntriesSpy);
tabChannelId.forEach((item: string) => {
nock("https://www.youtube.com")
.get(`/feeds/videos.xml?channel_id=${item}`)
.replyWithFile(
200,
joinPath(__dirname, `RessourcesTest/RealRessources/${item}.rss`),
{ "content-type": "text/xml", charset: "utf-8" }
)
.persist();
});
ml.startAll();
// here we're testing the first call
// when
await Promise.all([
events.once(ml.listenerArray[0], "update"),
events.once(ml.listenerArray[1], "update"),
events.once(ml.listenerArray[2], "update"),
]);
//expect
expect(updateSpy).to.have.been.calledThrice;
expect(newEntriesSpy).to.have.been.calledThrice;
// here we're testing the second call for the first listener
// given
updateSpy.resetHistory();
newEntriesSpy.resetHistory();
// when
await clock.tickAsync(10000);
await events.once(ml.listenerArray[0], "update");
//expect
expect(updateSpy).to.have.been.calledOnce;
expect(newEntriesSpy).to.not.have.been.called;
// here we're testing the thrid call for the first listener and second for the second listener
// given
updateSpy.resetHistory();
// when
await clock.tickAsync(10000);
await Promise.all([
events.once(ml.listenerArray[0], "update"),
events.once(ml.listenerArray[1], "update"),
]);
//expect
expect(updateSpy).to.have.been.calledTwice;
expect(newEntriesSpy).to.not.have.been.called;
// here we're testing the fourth call for the first listener and second for the third listener
// given
updateSpy.resetHistory();
// when
await clock.tickAsync(10000);
await Promise.all([
events.once(ml.listenerArray[0], "update"),
events.once(ml.listenerArray[2], "update"),
]);
//expect
expect(updateSpy).to.have.been.calledTwice;
expect(newEntriesSpy).to.not.have.been.called;
ml.stopAll();
});
const updateSpy = sinon.spy();
const newEntriesSpy = sinon.spy();
const tabChannelId = [
"UCOuIgj0CYCXCvjWywjDbauw",
"UCh2YBKhYIy-_LtfCIn2Jycg",
"UCY7klexd1qEqxgqYK6W7BVQ",
];
ml.on("update", updateSpy);
ml.on("newEntries", newEntriesSpy);
tabChannelId.forEach((item: string) => {
nock("https://www.youtube.com")
.get(`/feeds/videos.xml?channel_id=${item}`)
.replyWithFile(
200,
path.join(__dirname, `RessourcesTest/RealRessources/${item}.rss`),
{ "content-type": "text/xml", charset: "utf-8" }
)
.persist();
});
ml.startAll();
// here we're testing the first call
// when
await Promise.all([
events.once(ml.listenerArray[0], "update"),
events.once(ml.listenerArray[1], "update"),
events.once(ml.listenerArray[2], "update"),
]);
//expect
expect(updateSpy).to.have.been.calledThrice;
expect(newEntriesSpy).to.have.been.calledThrice;
// here we're testing the second call for the first listener
// given
updateSpy.resetHistory();
newEntriesSpy.resetHistory();
// when
await clock.tickAsync(10000);
await events.once(ml.listenerArray[0], "update");
//expect
expect(updateSpy).to.have.been.calledOnce;
expect(newEntriesSpy).to.not.have.been.called;
// here we're testing the thrid call for the first listener and second for the second listener
// given
updateSpy.resetHistory();
// when
await clock.tickAsync(10000);
await Promise.all([
events.once(ml.listenerArray[0], "update"),
events.once(ml.listenerArray[1], "update"),
]);
//expect
expect(updateSpy).to.have.been.calledTwice;
expect(newEntriesSpy).to.not.have.been.called;
// here we're testing the fourth call for the first listener and second for the third listener
// given
updateSpy.resetHistory();
// when
await clock.tickAsync(10000);
await Promise.all([
events.once(ml.listenerArray[0], "update"),
events.once(ml.listenerArray[2], "update"),
]);
//expect
expect(updateSpy).to.have.been.calledTwice;
expect(newEntriesSpy).to.not.have.been.called;
ml.stopAll();
});
it("should call correctly the events with a new entry (no aggregation)", async function () {
// given
const clock = sinon.useFakeTimers();
const ml = new ManageListener({
path: "tests/RessourcesTest/RealRessources/save.json",
await withFile(async ({ path }) => {
// given
const clock = sinon.useFakeTimers();
const ml = new ManageListener(path);
await ml.load();
for (const item of dataWithHistory) await ml.addNewListener(item);
const updateSpy = sinon.spy();
const newEntriesSpy = sinon.spy();
const tabChannelId = [
"UCOuIgj0CYCXCvjWywjDbauw",
"UCh2YBKhYIy-_LtfCIn2Jycg",
"UCY7klexd1qEqxgqYK6W7BVQ",
];
ml.on("update", updateSpy);
ml.on("newEntries", newEntriesSpy);
tabChannelId.forEach((item: string) => {
nock("https://www.youtube.com")
.get(`/feeds/videos.xml?channel_id=${item}`)
.once()
.replyWithFile(
200,
joinPath(__dirname, `RessourcesTest/RealRessources/${item}.rss`),
{ "content-type": "text/xml", charset: "utf-8" }
);
});
ml.startAll();
// here we're testing the first call
// when
await Promise.all([
events.once(ml.listenerArray[0], "update"),
events.once(ml.listenerArray[1], "update"),
events.once(ml.listenerArray[2], "update"),
]);
//expect
expect(updateSpy).to.have.been.calledThrice;
expect(newEntriesSpy).to.not.have.been.called;
// here we're testing the second call for the first listener
// given
updateSpy.resetHistory();
newEntriesSpy.resetHistory();
tabChannelId.forEach((item: string) => {
nock("https://www.youtube.com")
.get(`/feeds/videos.xml?channel_id=${item}`)
.replyWithFile(
200,
joinPath(
__dirname,
`RessourcesTest/RealRessources/WithUpdate/${item}.rss`
),
{ "content-type": "text/xml", charset: "utf-8" }
)
.persist();
});
// when
await clock.tickAsync(10000);
await events.once(ml.listenerArray[0], "update");
//expect
expect(updateSpy).to.have.been.calledOnce;
expect(newEntriesSpy).to.have.been.calledOnce;
// here we're testing the thrid call for the first listener and second for the second listener
// given
updateSpy.resetHistory();
newEntriesSpy.resetHistory();
// when
await clock.tickAsync(10000);
await Promise.all([
events.once(ml.listenerArray[0], "update"),
events.once(ml.listenerArray[1], "update"),
]);
//expect
expect(updateSpy).to.have.been.calledTwice;
expect(newEntriesSpy).to.have.been.calledOnce;
// here we're testing the fourth call for the first listener and second for the third listener
// given
updateSpy.resetHistory();
newEntriesSpy.resetHistory();
// when
await clock.tickAsync(10000);
await Promise.all([
events.once(ml.listenerArray[0], "update"),
events.once(ml.listenerArray[2], "update"),
]);
//expect
expect(updateSpy).to.have.been.calledTwice;
expect(newEntriesSpy).to.have.been.calledOnce;
ml.stopAll();
});
const updateSpy = sinon.spy();
const newEntriesSpy = sinon.spy();
const tabChannelId = [
"UCOuIgj0CYCXCvjWywjDbauw",
"UCh2YBKhYIy-_LtfCIn2Jycg",
"UCY7klexd1qEqxgqYK6W7BVQ",
];
ml.on("update", updateSpy);
ml.on("newEntries", newEntriesSpy);
tabChannelId.forEach((item: string) => {
nock("https://www.youtube.com")
.get(`/feeds/videos.xml?channel_id=${item}`)
.once()
.replyWithFile(
200,
path.join(__dirname, `RessourcesTest/RealRessources/${item}.rss`),
{ "content-type": "text/xml", charset: "utf-8" }
);
});
ml.startAll();
// here we're testing the first call
// when
await Promise.all([
events.once(ml.listenerArray[0], "update"),
events.once(ml.listenerArray[1], "update"),
events.once(ml.listenerArray[2], "update"),
]);
//expect
expect(updateSpy).to.have.been.calledThrice;
expect(newEntriesSpy).to.not.have.been.called;
// here we're testing the second call for the first listener
// given
updateSpy.resetHistory();
newEntriesSpy.resetHistory();
tabChannelId.forEach((item: string) => {
nock("https://www.youtube.com")
.get(`/feeds/videos.xml?channel_id=${item}`)
.replyWithFile(
200,
path.join(
__dirname,
`RessourcesTest/RealRessources/WithUpdate/${item}.rss`
),
{ "content-type": "text/xml", charset: "utf-8" }
)
.persist();
});
// when
await clock.tickAsync(10000);
await events.once(ml.listenerArray[0], "update");
//expect
expect(updateSpy).to.have.been.calledOnce;
expect(newEntriesSpy).to.have.been.calledOnce;
// here we're testing the thrid call for the first listener and second for the second listener
// given
updateSpy.resetHistory();
newEntriesSpy.resetHistory();
// when
await clock.tickAsync(10000);
await Promise.all([
events.once(ml.listenerArray[0], "update"),
events.once(ml.listenerArray[1], "update"),
]);
//expect
expect(updateSpy).to.have.been.calledTwice;
expect(newEntriesSpy).to.have.been.calledOnce;
// here we're testing the fourth call for the first listener and second for the third listener
// given
updateSpy.resetHistory();
newEntriesSpy.resetHistory();
// when
await clock.tickAsync(10000);
await Promise.all([
events.once(ml.listenerArray[0], "update"),
events.once(ml.listenerArray[2], "update"),
]);
//expect
expect(updateSpy).to.have.been.calledTwice;
expect(newEntriesSpy).to.have.been.calledOnce;
ml.stopAll();
});
it("should call correctly the events (with aggregation)", async function () {
// given
const clock = sinon.useFakeTimers();
const ml = new ManageListener({
timeloop: 30,
path: "tests/RessourcesTest/RealRessources/save_no_history.json",
});
// it("should call correctly the events (with aggregation)", async function () {
// // given
// const clock = sinon.useFakeTimers();
// const ml = new ManageListener({
// timeloop: 30,
// path: "tests/RessourcesTest/RealRessources/save_no_history.json",
// });
const updateSpy = sinon.spy((obj) => console.log(obj));
const newEntriesSpy = sinon.spy();
// const updateSpy = sinon.spy((obj) => console.log(obj));
// const newEntriesSpy = sinon.spy();
const tabChannelId = [
"UCOuIgj0CYCXCvjWywjDbauw",
"UCh2YBKhYIy-_LtfCIn2Jycg",
"UCY7klexd1qEqxgqYK6W7BVQ",
];
// const tabChannelId = [
// "UCOuIgj0CYCXCvjWywjDbauw",
// "UCh2YBKhYIy-_LtfCIn2Jycg",
// "UCY7klexd1qEqxgqYK6W7BVQ",
// ];
ml.on("update", updateSpy);
ml.on("newEntries", newEntriesSpy);
tabChannelId.forEach((item: string) => {
nock("https://www.youtube.com")
.get(`/feeds/videos.xml?channel_id=${item}`)
.replyWithFile(
200,
path.join(__dirname, `RessourcesTest/RealRessources/${item}.rss`),
{ "content-type": "text/xml", charset: "utf-8" }
)
.persist();
});
ml.startAll();
// ml.on("update", updateSpy);
// ml.on("newEntries", newEntriesSpy);
// tabChannelId.forEach((item: string) => {
// nock("https://www.youtube.com")
// .get(`/feeds/videos.xml?channel_id=${item}`)
// .replyWithFile(
// 200,
// path.join(__dirname, `RessourcesTest/RealRessources/${item}.rss`),
// { "content-type": "text/xml", charset: "utf-8" }
// )
// .persist();
// });
// ml.startAll();
// when
await Promise.all([
events.once(ml.listenerArray[0], "update"),
events.once(ml.listenerArray[1], "update"),
events.once(ml.listenerArray[2], "update"),
]);
// // when
// await Promise.all([
// events.once(ml.listenerArray[0], "update"),
// events.once(ml.listenerArray[1], "update"),
// events.once(ml.listenerArray[2], "update"),
// ]);
//expect
expect(updateSpy).to.have.been.calledOnce;
expect(newEntriesSpy).to.have.been.calledOnce;
// //expect
// expect(updateSpy).to.have.been.calledOnce;
// expect(newEntriesSpy).to.have.been.calledOnce;
// given
updateSpy.resetHistory();
newEntriesSpy.resetHistory();
// // given
// updateSpy.resetHistory();
// newEntriesSpy.resetHistory();
// when
await clock.tickAsync(10000);
await events.once(ml.listenerArray[0], "update");
// // when
// await clock.tickAsync(10000);
// await events.once(ml.listenerArray[0], "update");
//expect
expect(updateSpy).to.not.have.been.called;
expect(newEntriesSpy).to.not.have.been.called;
// //expect
// expect(updateSpy).to.not.have.been.called;
// expect(newEntriesSpy).to.not.have.been.called;
// when
await clock.tickAsync(10000);
await Promise.all([
events.once(ml.listenerArray[0], "update"),
events.once(ml.listenerArray[1], "update"),
]);
// // when
// await clock.tickAsync(10000);
// await Promise.all([
// events.once(ml.listenerArray[0], "update"),
// events.once(ml.listenerArray[1], "update"),
// ]);
//expect
expect(updateSpy).to.not.have.been.called;
expect(newEntriesSpy).to.not.have.been.called;
// //expect
// expect(updateSpy).to.not.have.been.called;
// expect(newEntriesSpy).to.not.have.been.called;
// when
await clock.tickAsync(10000);
await Promise.all([
events.once(ml.listenerArray[0], "update"),
events.once(ml.listenerArray[2], "update"),
]);
// // when
// await clock.tickAsync(10000);
// await Promise.all([
// events.once(ml.listenerArray[0], "update"),
// events.once(ml.listenerArray[2], "update"),
// ]);
//expect
expect(updateSpy).to.have.been.calledOnce;
expect(newEntriesSpy).to.not.have.been.called;
// //expect
// expect(updateSpy).to.have.been.calledOnce;
// expect(newEntriesSpy).to.not.have.been.called;
ml.stopAll();
});
// ml.stopAll();
// });
it("should call correctly the events with a new entry (with aggregation)", async function () {
// given
const clock = sinon.useFakeTimers();
const ml = new ManageListener({
timeloop: 30,
path: "tests/RessourcesTest/RealRessources/save.json",
});
// it("should call correctly the events with a new entry (with aggregation)", async function () {
// // given
// const clock = sinon.useFakeTimers();
// const ml = new ManageListener({
// timeloop: 30,
// path: "tests/RessourcesTest/RealRessources/save.json",
// });
const updateSpy = sinon.spy();
const newEntriesSpy = sinon.spy();
// const updateSpy = sinon.spy();
// const newEntriesSpy = sinon.spy();
const tabChannelId = [
"UCOuIgj0CYCXCvjWywjDbauw",
"UCh2YBKhYIy-_LtfCIn2Jycg",
"UCY7klexd1qEqxgqYK6W7BVQ",
];
// const tabChannelId = [
// "UCOuIgj0CYCXCvjWywjDbauw",
// "UCh2YBKhYIy-_LtfCIn2Jycg",
// "UCY7klexd1qEqxgqYK6W7BVQ",
// ];
ml.on("update", updateSpy);
ml.on("newEntries", newEntriesSpy);
tabChannelId.forEach((item: string) => {
nock("https://www.youtube.com")
.get(`/feeds/videos.xml?channel_id=${item}`)
.once()
.replyWithFile(
200,
path.join(__dirname, `RessourcesTest/RealRessources/${item}.rss`),
{ "content-type": "text/xml", charset: "utf-8" }
);
});
ml.startAll();
// ml.on("update", updateSpy);
// ml.on("newEntries", newEntriesSpy);
// tabChannelId.forEach((item: string) => {
// nock("https://www.youtube.com")
// .get(`/feeds/videos.xml?channel_id=${item}`)
// .once()
// .replyWithFile(
// 200,
// path.join(__dirname, `RessourcesTest/RealRessources/${item}.rss`),
// { "content-type": "text/xml", charset: "utf-8" }
// );
// });
// ml.startAll();
// when
await Promise.all([
events.once(ml.listenerArray[0], "update"),
events.once(ml.listenerArray[1], "update"),
events.once(ml.listenerArray[2], "update"),
]);
// // when
// await Promise.all([
// events.once(ml.listenerArray[0], "update"),
// events.once(ml.listenerArray[1], "update"),
// events.once(ml.listenerArray[2], "update"),
// ]);
//expect
expect(updateSpy).to.have.been.calledOnce;
expect(newEntriesSpy).to.not.have.been.called;
// //expect
// expect(updateSpy).to.have.been.calledOnce;
// expect(newEntriesSpy).to.not.have.been.called;
// given
updateSpy.resetHistory();
// // given
// updateSpy.resetHistory();
tabChannelId.forEach((item: string) => {
nock("https://www.youtube.com")
.get(`/feeds/videos.xml?channel_id=${item}`)
.replyWithFile(
200,
path.join(
__dirname,
`RessourcesTest/RealRessources/WithUpdate/${item}.rss`
),
{ "content-type": "text/xml", charset: "utf-8" }
)
.persist();
});
// tabChannelId.forEach((item: string) => {
// nock("https://www.youtube.com")
// .get(`/feeds/videos.xml?channel_id=${item}`)
// .replyWithFile(
// 200,
// path.join(
// __dirname,
// `RessourcesTest/RealRessources/WithUpdate/${item}.rss`
// ),
// { "content-type": "text/xml", charset: "utf-8" }
// )
// .persist();
// });
// when
await clock.tickAsync(10000);
await events.once(ml.listenerArray[0], "update");
// // when
// await clock.tickAsync(10000);
// await events.once(ml.listenerArray[0], "update");
//expect
expect(updateSpy).to.not.have.been.called;
expect(newEntriesSpy).to.not.have.been.called;
// //expect
// expect(updateSpy).to.not.have.been.called;
// expect(newEntriesSpy).to.not.have.been.called;
// when
await clock.tickAsync(10000);
await Promise.all([
events.once(ml.listenerArray[0], "update"),
events.once(ml.listenerArray[1], "update"),
]);
// // when
// await clock.tickAsync(10000);
// await Promise.all([
// events.once(ml.listenerArray[0], "update"),
// events.once(ml.listenerArray[1], "update"),
// ]);
//expect
expect(updateSpy).to.not.have.been.called;
expect(newEntriesSpy).to.not.have.been.called;
// //expect
// expect(updateSpy).to.not.have.been.called;
// expect(newEntriesSpy).to.not.have.been.called;
// when
await clock.tickAsync(10000);
await Promise.all([
events.once(ml.listenerArray[0], "update"),
events.once(ml.listenerArray[2], "update"),
]);
// // when
// await clock.tickAsync(10000);
// await Promise.all([
// events.once(ml.listenerArray[0], "update"),
// events.once(ml.listenerArray[2], "update"),
// ]);
//expect
expect(updateSpy).to.have.been.calledOnce;
expect(newEntriesSpy).to.have.been.calledOnce;
// //expect
// expect(updateSpy).to.have.been.calledOnce;
// expect(newEntriesSpy).to.have.been.calledOnce;
ml.stopAll();
});
// ml.stopAll();
// });
});
});

View File

@ -0,0 +1,54 @@
import { SqliteTools } from "../src/sqlite-tools";
import { ListenerRSSInfos } from "listener-rss";
// testing
import * as chai from "chai";
import sinon from "ts-sinon";
import sinonChai from "sinon-chai";
import { withFile } from "tmp-promise";
chai.use(sinonChai);
const expect = chai.expect;
const dataWithHistory: ListenerRSSInfos[] = require("./RessourcesTest/RealRessources/save.json");
const dataWithoutHistory = dataWithHistory.map((data) => ({
...data,
lastEntriesLinks: [],
}));
describe("test sqlite tools class", () => {
it("should create a .db file and fill him", async () => {
await withFile(async ({ path }) => {
// given
const dbTools = new SqliteTools(path);
await dbTools.ensureTableExists();
// when
const oldValues: ListenerRSSInfos[] = await dbTools.fetchAll();
for (const item of dataWithoutHistory) await dbTools.insertListener(item);
const newValues: ListenerRSSInfos[] = await dbTools.fetchAll();
// expect
expect(oldValues).to.be.empty;
expect(newValues).to.have.lengthOf(3);
expect(newValues).to.be.eql(dataWithoutHistory);
});
});
it("should update the values of the databases", async () => {
await withFile(async ({ path }) => {
// given
const dbTools = new SqliteTools(path);
await dbTools.ensureTableExists();
for (const item of dataWithoutHistory) await dbTools.insertListener(item);
//when
await dbTools.updateAll(dataWithHistory);
const values: ListenerRSSInfos[] = await dbTools.fetchAll();
expect(values).to.be.eql(dataWithHistory);
});
});
});

View File

@ -1,7 +1,7 @@
{
"compilerOptions": {
"target": "es2018",
"module": "es2015",
"module": "commonjs",
"lib": ["es6"],
"allowJs": true,
"outDir": "build",