Using pino as a log writer + Append the Generics to make Routing more scalable
This commit is contained in:
parent
d1f1165136
commit
01ca99c4e7
4455
package-lock.json
generated
4455
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
|
@ -29,6 +29,7 @@
|
||||||
"@types/nock": "^11.1.0",
|
"@types/nock": "^11.1.0",
|
||||||
"@types/node": "^15.3.0",
|
"@types/node": "^15.3.0",
|
||||||
"@types/node-fetch": "^2.5.10",
|
"@types/node-fetch": "^2.5.10",
|
||||||
|
"@types/pino": "^6.3.8",
|
||||||
"@types/sinon-chai": "^3.2.5",
|
"@types/sinon-chai": "^3.2.5",
|
||||||
"@typescript-eslint/eslint-plugin": "^4.23.0",
|
"@typescript-eslint/eslint-plugin": "^4.23.0",
|
||||||
"@typescript-eslint/parser": "^4.23.0",
|
"@typescript-eslint/parser": "^4.23.0",
|
||||||
|
@ -44,6 +45,7 @@
|
||||||
"mocha": "^8.4.0",
|
"mocha": "^8.4.0",
|
||||||
"nock": "^13.0.11",
|
"nock": "^13.0.11",
|
||||||
"node-fetch": "^2.6.1",
|
"node-fetch": "^2.6.1",
|
||||||
|
"pino": "^6.11.3",
|
||||||
"prettier": "^2.3.0",
|
"prettier": "^2.3.0",
|
||||||
"sinon-chai": "^3.6.0",
|
"sinon-chai": "^3.6.0",
|
||||||
"tmp-promise": "^3.0.2",
|
"tmp-promise": "^3.0.2",
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { Client, Message, TextChannel } from 'discord.js';
|
import { Client, Message, TextChannel } from 'discord.js';
|
||||||
import dedent from 'ts-dedent';
|
|
||||||
import { ImplementableApi } from './implementableApi';
|
import { ImplementableApi } from './implementableApi';
|
||||||
|
|
||||||
import { once as eventsOnce } from 'events';
|
import { once as eventsOnce } from 'events';
|
||||||
|
@ -29,7 +28,12 @@ type ChannelsType = {
|
||||||
ChannelPeerTube: TextChannel;
|
ChannelPeerTube: TextChannel;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DiscordParser extends ImplementableApi {
|
type TBaseDiscordMessageType = ('addListener' | 'newEntriesNotify') &
|
||||||
|
ImplementableApi.TBaseMessageType;
|
||||||
|
|
||||||
|
class DiscordParser<
|
||||||
|
T extends TBaseDiscordMessageType
|
||||||
|
> extends ImplementableApi<T> {
|
||||||
readonly botPrefix: string;
|
readonly botPrefix: string;
|
||||||
readonly channels: {
|
readonly channels: {
|
||||||
[key: string]: TextChannel;
|
[key: string]: TextChannel;
|
||||||
|
@ -46,9 +50,9 @@ class DiscordParser extends ImplementableApi {
|
||||||
this.settingEvents();
|
this.settingEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
static async instanciate(
|
static async instanciate<T extends TBaseDiscordMessageType>(
|
||||||
config: DiscordParser.Config
|
config: DiscordParser.Config
|
||||||
): Promise<DiscordParser.ConstructorPattern> {
|
): Promise<DiscordParser<T>> {
|
||||||
const client = new Client();
|
const client = new Client();
|
||||||
client.login(config.token);
|
client.login(config.token);
|
||||||
await eventsOnce(client, 'ready');
|
await eventsOnce(client, 'ready');
|
||||||
|
@ -63,12 +67,12 @@ class DiscordParser extends ImplementableApi {
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return new DiscordParser<T>({
|
||||||
name: config.name,
|
name: config.name,
|
||||||
channels: channels,
|
channels: channels,
|
||||||
client: client,
|
client: client,
|
||||||
botPrefix: config.keyWord,
|
botPrefix: config.keyWord,
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static getTextChannel(client: Client, id: string): TextChannel {
|
private static getTextChannel(client: Client, id: string): TextChannel {
|
||||||
|
@ -78,7 +82,7 @@ class DiscordParser extends ImplementableApi {
|
||||||
return channel;
|
return channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public receivedMessage(message: ImplementableApi.Message) {
|
public receivedMessage(message: ImplementableApi.Message<T>) {
|
||||||
switch (message.type) {
|
switch (message.type) {
|
||||||
case 'newEntriesNotify':
|
case 'newEntriesNotify':
|
||||||
this.sendMsgYtb(
|
this.sendMsgYtb(
|
||||||
|
@ -114,13 +118,14 @@ class DiscordParser extends ImplementableApi {
|
||||||
if (msg_splitted[0] === this.botPrefix) {
|
if (msg_splitted[0] === this.botPrefix) {
|
||||||
switch (msg_splitted[1]) {
|
switch (msg_splitted[1]) {
|
||||||
case 'add':
|
case 'add':
|
||||||
const send_message: ImplementableApi.Message = {
|
const send_message: ImplementableApi.Message<TBaseDiscordMessageType> =
|
||||||
|
{
|
||||||
rawContent: {
|
rawContent: {
|
||||||
address: msg_splitted[2],
|
address: msg_splitted[2],
|
||||||
user: message.author.toString(),
|
user: message.author.toString(),
|
||||||
date: message.createdAt.toUTCString(),
|
date: message.createdAt.toUTCString(),
|
||||||
},
|
},
|
||||||
type: 'newListener',
|
type: 'addListener',
|
||||||
};
|
};
|
||||||
message.channel.send('Ceci est un feedback');
|
message.channel.send('Ceci est un feedback');
|
||||||
this.emit('addListener', send_message);
|
this.emit('addListener', send_message);
|
||||||
|
|
|
@ -10,14 +10,17 @@ namespace ImplementableApi {
|
||||||
* the type field permit to know which type of message it is
|
* the type field permit to know which type of message it is
|
||||||
* rawContent field is the string content of the message
|
* rawContent field is the string content of the message
|
||||||
*/
|
*/
|
||||||
export type Message = {
|
export type Message<T extends TBaseMessageType> = {
|
||||||
idListener?: number;
|
idListener?: number;
|
||||||
type: 'newEntriesNotify' | 'newListener';
|
type: T | 'logging';
|
||||||
rawContent: any;
|
rawContent: any;
|
||||||
};
|
};
|
||||||
|
export type TBaseMessageType = string;
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class ImplementableApi extends EventEmitter {
|
abstract class ImplementableApi<
|
||||||
|
T extends ImplementableApi.TBaseMessageType
|
||||||
|
> extends EventEmitter {
|
||||||
readonly name: string;
|
readonly name: string;
|
||||||
|
|
||||||
constructor(readonly config: ImplementableApi.Config) {
|
constructor(readonly config: ImplementableApi.Config) {
|
||||||
|
@ -25,7 +28,7 @@ abstract class ImplementableApi extends EventEmitter {
|
||||||
this.name = config.name;
|
this.name = config.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract receivedMessage(message: ImplementableApi.Message): void;
|
public abstract receivedMessage(message: ImplementableApi.Message<T>): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export { ImplementableApi };
|
export { ImplementableApi };
|
||||||
|
|
|
@ -1,11 +1,6 @@
|
||||||
import { ImplementableApi } from './implementableApi';
|
import { ImplementableApi } from './implementableApi';
|
||||||
import {
|
|
||||||
appendFileSync,
|
import pino, { Logger } from 'pino';
|
||||||
closeSync,
|
|
||||||
openSync,
|
|
||||||
writeFile,
|
|
||||||
writeFileSync,
|
|
||||||
} from 'fs';
|
|
||||||
|
|
||||||
namespace LogWriter {
|
namespace LogWriter {
|
||||||
export type Config = ImplementableApi.Config & {
|
export type Config = ImplementableApi.Config & {
|
||||||
|
@ -17,33 +12,30 @@ namespace LogWriter {
|
||||||
*/
|
*/
|
||||||
class LogWriter extends ImplementableApi {
|
class LogWriter extends ImplementableApi {
|
||||||
readonly path: string;
|
readonly path: string;
|
||||||
|
readonly logger: Logger;
|
||||||
|
|
||||||
constructor(readonly config: LogWriter.Config) {
|
constructor(readonly config: LogWriter.Config) {
|
||||||
super(config);
|
super(config);
|
||||||
this.path = config.path;
|
this.path = config.path;
|
||||||
|
|
||||||
this.firstWrite();
|
this.logger = pino(pino.destination({ dest: config.path }));
|
||||||
}
|
|
||||||
|
|
||||||
private firstWrite() {
|
|
||||||
this.writeMsg('LogWriter is running');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private writeMsg(message: string): void;
|
private writeMsg(message: string): void;
|
||||||
private writeMsg(message: ImplementableApi.Message): void;
|
private writeMsg(message: ImplementableApi.Message): void;
|
||||||
private writeMsg(message: ImplementableApi.Message | string) {
|
private writeMsg(message: ImplementableApi.Message | string) {
|
||||||
if (typeof message !== 'string')
|
if (typeof message !== 'string')
|
||||||
message = `[${message.type} :: ${new Date().toISOString()}] ${
|
message = `[${message.type}] ${
|
||||||
message.rawContent
|
typeof message.rawContent === 'string'
|
||||||
|
? message.rawContent
|
||||||
|
: JSON.stringify(message.rawContent)
|
||||||
} ${
|
} ${
|
||||||
message.idListener ??
|
message.idListener ??
|
||||||
`( listener_id : ${message.idListener} )\n`
|
`( listener_id : ${message.idListener} )\n`
|
||||||
}`;
|
}`;
|
||||||
|
|
||||||
const fd = openSync(this.path, 'a');
|
// const str = `[${new Date().toISOString()}] ${message}\n`;
|
||||||
const str = `[${new Date().toISOString()}] ${message}\n`;
|
this.logger.info(message);
|
||||||
appendFileSync(fd, str);
|
|
||||||
closeSync(fd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public receivedMessage(message: ImplementableApi.Message) {
|
public receivedMessage(message: ImplementableApi.Message) {
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
import { ImplementableApi } from './implementableApi';
|
import { ImplementableApi } from './implementableApi';
|
||||||
|
|
||||||
import { DiscordParser } from './discordParser';
|
|
||||||
import { LogWriter } from './logWriter';
|
|
||||||
import { PeerTubeRequester } from './peertubeRequester';
|
|
||||||
import EventEmitter from 'events';
|
import EventEmitter from 'events';
|
||||||
|
|
||||||
namespace Router {
|
namespace Router {
|
||||||
|
@ -12,44 +9,57 @@ namespace Router {
|
||||||
};
|
};
|
||||||
export type InternalConfig = {
|
export type InternalConfig = {
|
||||||
events: EventsType[];
|
events: EventsType[];
|
||||||
apis: {
|
|
||||||
apiName: string;
|
|
||||||
}[];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// export type GlobalConfig = {
|
|
||||||
// router: InternalConfig;
|
|
||||||
// };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Router extends EventEmitter {
|
class Router<
|
||||||
api_array: { [key: string]: ImplementableApi } = {};
|
MessageType extends ImplementableApi.TBaseMessageType
|
||||||
routes: Router.InternalConfig;
|
> extends EventEmitter {
|
||||||
|
api_array: { [key: string]: ImplementableApi<MessageType> } = {};
|
||||||
|
events: Router.EventsType[];
|
||||||
|
|
||||||
constructor(readonly config: Router.EventsType[]) {
|
constructor(readonly config: Router.EventsType[]) {
|
||||||
super();
|
super();
|
||||||
this.routes = { events: config, apis: [] };
|
this.events = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
public injectDependency(api: ImplementableApi): void {
|
public injectDependency(api: ImplementableApi<MessageType>): void {
|
||||||
if (api.name in this.api_array)
|
if (api.name in this.api_array)
|
||||||
throw `The api name '${api.name}' is already take`;
|
throw `The api name '${api.name}' is already take`;
|
||||||
this.routes.apis.push({ apiName: api.name });
|
|
||||||
this.api_array[api.name] = api;
|
this.api_array[api.name] = api;
|
||||||
|
|
||||||
this.setEvents(api);
|
this.setEvents(api);
|
||||||
|
|
||||||
|
this.receivedMessage({
|
||||||
|
rawContent: `The dependency \`${api.name}\` was well injected into the router`,
|
||||||
|
type: 'logging',
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private setEvents(api: ImplementableApi) {
|
private setEvents(api: ImplementableApi<MessageType>) {
|
||||||
for (const eventName in this.routes.events.map(
|
for (const event of this.events.filter(
|
||||||
(ev) => ev.type === 'received'
|
(ev) => ev.type === 'received'
|
||||||
))
|
)) {
|
||||||
api.on(eventName, () => this.emit(eventName));
|
api.on(event.name, (obj: ImplementableApi.Message<MessageType>) => {
|
||||||
|
this.receivedMessage({
|
||||||
|
type: 'logging',
|
||||||
|
rawContent: `A message of type \`${obj.type}\` was emited by \`${api.name}\` with the event \`${event.name}\``,
|
||||||
|
});
|
||||||
|
this.emit(event.name, obj);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public receivedMessage(message: ImplementableApi.Message) {
|
public receivedMessage(message: ImplementableApi.Message<MessageType>) {
|
||||||
for (const apiName in this.routes.apis)
|
this.redirectMessage({
|
||||||
this.api_array[apiName].receivedMessage(message);
|
rawContent: `A message of type \`${message.type}\` was received`,
|
||||||
|
type: 'logging',
|
||||||
|
});
|
||||||
|
this.redirectMessage(message);
|
||||||
|
}
|
||||||
|
private redirectMessage(message: ImplementableApi.Message<MessageType>) {
|
||||||
|
for (const api in this.api_array)
|
||||||
|
this.api_array[api].receivedMessage(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,77 +0,0 @@
|
||||||
import chai, { expect } from 'chai';
|
|
||||||
import sinon from 'ts-sinon';
|
|
||||||
import sinonChai from 'sinon-chai';
|
|
||||||
|
|
||||||
chai.use(sinonChai);
|
|
||||||
|
|
||||||
import { DiscordParser } from '../src/discordParser';
|
|
||||||
|
|
||||||
//data
|
|
||||||
const config: DiscordParser.Config = {
|
|
||||||
channelsId: {
|
|
||||||
idChannelPeerTube: 'peertubeID',
|
|
||||||
idChannelYtb: 'ytbChannel',
|
|
||||||
},
|
|
||||||
keyWord: 'myDiscordKeyword',
|
|
||||||
name: 'DiscordTestedInterface',
|
|
||||||
token: 'mySecretDiscordToken',
|
|
||||||
};
|
|
||||||
|
|
||||||
//mockeded imports
|
|
||||||
import { Channel, ChannelManager, Client } from 'discord.js';
|
|
||||||
|
|
||||||
describe.skip('test DiscordParser', function () {
|
|
||||||
let clientMockOn: sinon.SinonStub,
|
|
||||||
clientMockLogin: sinon.SinonStub,
|
|
||||||
channelStub: sinon.SinonStubbedInstance<Channel>,
|
|
||||||
channelManagerMockResolve: sinon.SinonStub;
|
|
||||||
|
|
||||||
before(() => {
|
|
||||||
clientMockOn = sinon.stub(Client.prototype, 'on');
|
|
||||||
clientMockOn.withArgs('message', sinon.match.func).onFirstCall();
|
|
||||||
clientMockOn.throws('Error, bad parameter or too much call');
|
|
||||||
|
|
||||||
clientMockLogin = sinon.stub(Client.prototype, 'login');
|
|
||||||
clientMockLogin
|
|
||||||
.withArgs(config.token)
|
|
||||||
.onFirstCall()
|
|
||||||
.resolves('ok')
|
|
||||||
.returnsThis();
|
|
||||||
clientMockLogin.throws('Error, bad parameter or too much call');
|
|
||||||
|
|
||||||
channelStub = sinon.createStubInstance(Channel);
|
|
||||||
|
|
||||||
channelManagerMockResolve = sinon.stub(
|
|
||||||
ChannelManager.prototype,
|
|
||||||
'resolve'
|
|
||||||
);
|
|
||||||
channelManagerMockResolve
|
|
||||||
.withArgs(config.channelsId.idChannelPeerTube)
|
|
||||||
.onFirstCall()
|
|
||||||
.returns(channelStub);
|
|
||||||
channelManagerMockResolve
|
|
||||||
.withArgs(config.channelsId.idChannelYtb)
|
|
||||||
.onFirstCall()
|
|
||||||
.returns(channelStub);
|
|
||||||
channelManagerMockResolve.throws("Error Bad id's or too much call");
|
|
||||||
});
|
|
||||||
|
|
||||||
after(() => {
|
|
||||||
clientMockOn.restore();
|
|
||||||
clientMockLogin.restore();
|
|
||||||
channelManagerMockResolve.restore();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('it will test the DiscordParser constructor', async function () {
|
|
||||||
//when
|
|
||||||
const discordParser = new DiscordParser(config);
|
|
||||||
|
|
||||||
// expect
|
|
||||||
expect(discordParser.token).to.be.eql(config.token);
|
|
||||||
await discordParser.channels.then((channels) => {
|
|
||||||
expect(channels.ChannelYtb.id).to.be.eql(
|
|
||||||
config.channelsId.idChannelYtb
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -5,42 +5,49 @@ import sinonChai from 'sinon-chai';
|
||||||
chai.use(sinonChai);
|
chai.use(sinonChai);
|
||||||
const expect = chai.expect;
|
const expect = chai.expect;
|
||||||
|
|
||||||
import { withFile } from 'tmp-promise';
|
import { ImplementableApi, Router } from '../src/index';
|
||||||
import { writeFileSync } from 'fs';
|
|
||||||
|
|
||||||
import { Router } from '../src/index';
|
// const well_build_routing_file: Router.GlobalConfig = require('./rsrc/wellBuildedRoutingFile.json');
|
||||||
import { DiscordParser } from '../src/discordParser';
|
|
||||||
import { LogWriter } from '../src/logWriter';
|
|
||||||
import { PeerTubeRequester } from '../src/peertubeRequester';
|
|
||||||
|
|
||||||
const well_build_routing_file: Router.GlobalConfig = require('./rsrc/wellBuildedRoutingFile.json');
|
const events: Router.EventsType[] = [
|
||||||
|
{
|
||||||
describe('testing the routing part', function () {
|
name: 'newEntries',
|
||||||
describe('testing the building part', function () {
|
type: 'emit',
|
||||||
it('it will test a normal building', async function () {
|
|
||||||
await withFile(
|
|
||||||
async (file) => {
|
|
||||||
const edit_config = {
|
|
||||||
...well_build_routing_file,
|
|
||||||
logWriter: {
|
|
||||||
...well_build_routing_file.logWriter,
|
|
||||||
...{ path: file.path },
|
|
||||||
},
|
},
|
||||||
};
|
{
|
||||||
const r = new Router(edit_config);
|
name: 'addListener',
|
||||||
|
type: 'received',
|
||||||
// expect(r.api_array['Discord']).to.be.instanceOf(
|
|
||||||
// DiscordParser
|
|
||||||
// );
|
|
||||||
expect(r.api_array['logWriter']).to.be.instanceOf(
|
|
||||||
LogWriter
|
|
||||||
);
|
|
||||||
expect(r.api_array['peertubeRequester']).to.be.instanceOf(
|
|
||||||
PeerTubeRequester
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
{ postfix: '.log' }
|
];
|
||||||
);
|
type AllowedEvents = 'newEntries' | 'addListener'; // need to match with the EventsType's names
|
||||||
|
|
||||||
|
class FakeApi extends ImplementableApi<AllowedEvents> {
|
||||||
|
constructor(conf: ImplementableApi.Config) {
|
||||||
|
super(conf);
|
||||||
|
}
|
||||||
|
|
||||||
|
receivedMessage(msg: ImplementableApi.Message<AllowedEvents>) {
|
||||||
|
// don't do anything
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe.only('testing the routing part', function () {
|
||||||
|
describe('testing the injection', function () {
|
||||||
|
it('will test the dependency injection', function () {
|
||||||
|
// given
|
||||||
|
const myRouter = new Router<AllowedEvents>(events);
|
||||||
|
const myObj = new FakeApi({ name: 'myFakeApi' });
|
||||||
|
// first expect
|
||||||
|
expect(myRouter.api_array).to.be.empty;
|
||||||
|
expect(myRouter.events).to.be.empty;
|
||||||
|
|
||||||
|
// when
|
||||||
|
myRouter.injectDependency(myObj);
|
||||||
|
|
||||||
|
// expect
|
||||||
|
expect(myRouter.api_array).to.have.keys(['myFakeApi']);
|
||||||
|
expect(myRouter.api_array['myFakeApi']).to.be.instanceOf(FakeApi);
|
||||||
|
expect(myRouter.events).to.be.empty;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('testing the data transmission', function () {
|
describe('testing the data transmission', function () {
|
||||||
|
@ -48,6 +55,31 @@ describe('testing the routing part', function () {
|
||||||
it('it will emit a new listener request', function () {});
|
it('it will emit a new listener request', function () {});
|
||||||
});
|
});
|
||||||
describe('testing the data reception', function () {
|
describe('testing the data reception', function () {
|
||||||
it('it will received a new entries notification', function () {});
|
it.only('it will received a new entries notification', function () {
|
||||||
|
//given
|
||||||
|
const myMessageWhoWouldBeSend: ImplementableApi.Message<AllowedEvents> =
|
||||||
|
{
|
||||||
|
rawContent: 'My content',
|
||||||
|
type: 'logging',
|
||||||
|
idListener: 5,
|
||||||
|
};
|
||||||
|
const myStub = sinon.stub(FakeApi.prototype, 'receivedMessage');
|
||||||
|
const myRouter = new Router([]);
|
||||||
|
const myObj = new FakeApi({ name: 'myFakeApi' });
|
||||||
|
myRouter.injectDependency(myObj);
|
||||||
|
|
||||||
|
// when
|
||||||
|
myRouter.receivedMessage(myMessageWhoWouldBeSend);
|
||||||
|
|
||||||
|
// expect
|
||||||
|
expect(myStub.firstCall).to.have.been.calledWith(
|
||||||
|
myMessageWhoWouldBeSend
|
||||||
|
);
|
||||||
|
expect(myStub.secondCall).to.have.been.calledWith({
|
||||||
|
rawContent:
|
||||||
|
'The dependency `myFakeApi` was well injected into the router',
|
||||||
|
type: 'logging',
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
import chai, { expect } from 'chai';
|
|
||||||
import sinon from 'ts-sinon';
|
|
||||||
import sinonChai from 'sinon-chai';
|
|
||||||
|
|
||||||
chai.use(sinonChai);
|
|
||||||
|
|
||||||
import { withDir } from 'tmp-promise';
|
|
||||||
import { existsSync, readFileSync } from 'fs';
|
|
||||||
|
|
||||||
import { LogWriter } from '../src/logWriter';
|
|
||||||
|
|
||||||
const config: LogWriter.Config = {
|
|
||||||
name: 'logWirterTested',
|
|
||||||
path: 'it will be set by tmp-promise',
|
|
||||||
};
|
|
||||||
|
|
||||||
describe('test logWriter', function () {
|
|
||||||
describe('constructor', function () {
|
|
||||||
it('will test the constructor with a new file', async function () {
|
|
||||||
await withDir(
|
|
||||||
async (dir) => {
|
|
||||||
const log_writer = new LogWriter({
|
|
||||||
...config,
|
|
||||||
...{ path: dir.path + '/toto.log' },
|
|
||||||
});
|
|
||||||
expect(existsSync(dir.path + '/toto.log')).to.be.true;
|
|
||||||
expect(
|
|
||||||
readFileSync(dir.path + '/toto.log', {
|
|
||||||
encoding: 'utf-8',
|
|
||||||
})
|
|
||||||
).to.match(/LogWriter is running\n+$/g);
|
|
||||||
},
|
|
||||||
{ unsafeCleanup: true }
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('received message', function () {
|
|
||||||
it('will test the print function', function () {});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
//presenter le projet . listener -> import sous forme de plugin
|
|
Loading…
Reference in New Issue
Block a user