"jest": "^29.5.0",
"ts-jest": "^29.1.0",
"typescript": "^5.0.4"
- },
- "tap": {
- "check-coverage": false,
- "jobs": 1
}
}
[":localhost 001 testbot :Welcome to the Internet Relay Chat Network testbot\r\n", "Received welcome message"]
]
},
- "double-CRLF": {
+ "doubleCRLF": {
"sent": [
["CAP LS 302", "Client sent CAP request"],
["NICK testbot", "Client sent NICK message"],
}
},
- "433-before-001": {
+ "_433before001": {
"sent": [
["CAP LS 302", "Client sent CAP request"],
["NICK testbot", "Client sent NICK message"],
"maxLineLength is as expected after 433"
]
},
- "convert-encoding": {
+ "convertEncoding": {
"causesException": [
":ubottu!ubottu@ubuntu/bot/ubottu MODE #ubuntu -bo *!~Brian@* ubottu\r\n",
"Elizabeth",
+++ /dev/null
-/* Mock irc server */
-
-var path = require('path');
-var fs = require('fs');
-var net = require('net');
-var tls = require('tls');
-var util = require('util');
-var EventEmitter = require('events').EventEmitter;
-
-var MockIrcd = function(port, encoding, isSecure) {
- var self = this;
- var connectionClass;
- var options = {};
-
- if (isSecure) {
- connectionClass = tls;
- options = {
- key: fs.readFileSync(path.resolve(__dirname, 'data/ircd.key')),
- cert: fs.readFileSync(path.resolve(__dirname, 'data/ircd.pem'))
- };
- } else {
- connectionClass = net;
- }
-
- this.port = port || (isSecure ? 6697 : 6667);
- this.encoding = encoding || 'utf-8';
- this.incoming = [];
- this.outgoing = [];
-
- this.server = connectionClass.createServer(options, function(c) {
- c.on('data', function(data) {
- var msg = data.toString(self.encoding).split('\r\n').filter(function(m) { return m; });
- self.incoming = self.incoming.concat(msg);
- });
-
- self.on('send', function(data) {
- self.outgoing.push(data);
- c.write(data);
- });
-
- c.on('end', function() {
- self.emit('end');
- });
- });
-
- this.server.listen(this.port);
-};
-util.inherits(MockIrcd, EventEmitter);
-
-MockIrcd.prototype.send = function(data) {
- this.emit('send', data);
-};
-
-MockIrcd.prototype.close = function() {
- this.server.close();
-};
-
-MockIrcd.prototype.getIncomingMsgs = function() {
- return this.incoming;
-};
-
-var fixtures = require('./data/fixtures');
-module.exports.getFixtures = function(testSuite) {
- return fixtures[testSuite];
-};
-
-module.exports.MockIrcd = function(port, encoding, isSecure) {
- return new MockIrcd(port, encoding, isSecure);
-};
--- /dev/null
+/* eslint-disable @typescript-eslint/no-explicit-any */
+import * as path from "node:path";
+import * as fs from "node:fs";
+import * as net from "node:net";
+import * as tls from "node:tls";
+import EventEmitter from "node:events";
+import { AddressInfo } from "node:net";
+
+export class MockIrcd extends EventEmitter {
+ incoming: unknown[] = [];
+ outgoing: unknown[] = [];
+ server: net.Server;
+
+ constructor(public readonly encoding: BufferEncoding = "utf-8", isSecure = false) {
+ super();
+ let connectionFn;
+ let options = {};
+
+ if (isSecure) {
+ connectionFn = (opts: any, f: (c: net.Socket) => void) => tls.createServer(opts, f);
+ options = {
+ key: fs.readFileSync(path.resolve(__dirname, 'data/ircd.key')),
+ cert: fs.readFileSync(path.resolve(__dirname, 'data/ircd.pem'))
+ };
+ }
+ else {
+ connectionFn = (opts: any, f: (c: net.Socket) => void) => net.createServer(opts, f);
+ }
+
+ this.server = connectionFn(options, (c) => {
+ c.on('data', (data) => {
+ const msg = data.toString(encoding).split('\r\n').filter(function(m) { return m; });
+ this.incoming = this.incoming.concat(msg);
+ });
+
+ this.on('send', (data) => {
+ this.outgoing.push(data);
+ c.write(data);
+ });
+
+ c.on('end', () => {
+ this.emit('end');
+ });
+ });
+ }
+
+ async listen() {
+ return new Promise<number>((resolve) => {
+ this.server.listen(0, () => {
+ resolve((this.server.address() as AddressInfo).port)
+ });
+ });
+ }
+
+ send(data: string) {
+ this.emit('send', data);
+ }
+
+ close() {
+ this.server.close();
+ }
+
+ getIncomingMsgs() {
+ return this.incoming;
+ }
+}
+++ /dev/null
-var irc = require('../lib/irc');
-var test = require('tape');
-
-var testHelpers = require('./helpers');
-
-test('connect and sets hostmask when nick in use', function(t) {
- var client, mock, expected;
-
- mock = testHelpers.MockIrcd();
- client = new irc.Client('localhost', 'testbot', {debug: true});
-
- expected = testHelpers.getFixtures('433-before-001');
-
- t.plan(expected.sent.length + expected.received.length + expected.clientInfo.length);
-
- mock.server.on('connection', function() {
- mock.send(':localhost 433 * testbot :Nickname is already in use.\r\n')
- mock.send(':localhost 001 testbot1 :Welcome to the Internet Relay Chat Network testbot\r\n');
- });
-
- client.on('registered', function() {
- t.equal(mock.outgoing[0], expected.received[0][0], expected.received[0][1]);
- t.equal(mock.outgoing[1], expected.received[1][0], expected.received[1][1]);
- client.disconnect(function() {
- t.equal(client.hostMask, 'testbot', 'hostmask is as expected after 433');
- t.equal(client.nick, 'testbot1', 'nick is as expected after 433');
- t.equal(client.maxLineLength, 482, 'maxLineLength is as expected after 433');
- });
- });
-
- mock.on('end', function() {
- var msgs = mock.getIncomingMsgs();
-
- for (var i = 0; i < msgs.length; i++) {
- t.equal(msgs[i], expected.sent[i][0], expected.sent[i][1]);
- }
- mock.close();
- });
-});
--- /dev/null
+import { MockIrcd } from './helpers';
+import { Client } from "../src";
+import { test, expect } from "@jest/globals";
+import { _433before001 as fixtures } from "./data/fixtures.json";
+
+test('connect and sets hostmask when nick in use', async () => {
+
+ const mock = new MockIrcd();
+ const client = new Client('localhost', 'testbot', {debug: true, port: await mock.listen()});
+
+ mock.server.on('connection', function() {
+ mock.send(':localhost 433 * testbot :Nickname is already in use.\r\n')
+ mock.send(':localhost 001 testbot1 :Welcome to the Internet Relay Chat Network testbot\r\n');
+ });
+
+ client.on('registered', function() {
+ expect(mock.outgoing[0]).toEqual(fixtures.received[0][0]);
+ expect(mock.outgoing[1]).toEqual(fixtures.received[1][0]);
+ client.disconnect(function() {
+ expect(client.hostMask).toEqual('testbot');
+ expect(client.nick).toEqual('testbot1');
+ expect(client.maxLineLength).toEqual(482);
+ });
+ });
+
+ mock.on('end', function() {
+ const msgs = mock.getIncomingMsgs();
+
+ for (let i = 0; i < msgs.length; i++) {
+ expect(msgs[i]).toEqual(fixtures.sent[i][0]);
+ }
+ mock.close();
+
+ expect.assertions(fixtures.sent.length + fixtures.received.length + fixtures.clientInfo.length);
+ });
+});
-var net = require('net');
+import { MockIrcd } from './helpers';
+import { Client } from "../src";
+import { test, expect, jest } from "@jest/globals";
-var irc = require('../lib/irc');
-var test = require('tape');
+test('user gets opped in auditorium', async () => {
+ const mock = new MockIrcd();
+ const client = new Client('localhost', 'testbot', {debug: true, port: await mock.listen()});
-var testHelpers = require('./helpers');
-
-test('user gets opped in auditorium', function(t) {
- var mock = testHelpers.MockIrcd();
- var client = new irc.Client('localhost', 'testbot', {debug: true});
-
- client.on('+mode', function(channel, by, mode, argument) {
- if (channel == '#auditorium' && argument == 'user') {
+ const modehandler = jest.fn((channel: string, by: string, mode: string, argument?: string) => {
+ if (channel === '#auditorium' && argument === 'user') {
client.disconnect();
}
});
+ client.on('+mode', modehandler);
+
mock.server.on('connection', function() {
// Initiate connection
mock.send(':localhost 001 testbot :Welcome to the Internet Relay Chat Network testbot\r\n');
mock.on('end', function() {
mock.close();
- t.end();
+ expect(modehandler).toBeCalled();
});
});
+++ /dev/null
-const irc = require('../lib/irc');
-const test = require('tape');
-const testHelpers = require('./helpers');
-const Iconv = require('iconv-lite');
-const chardet = require('chardet');
-const checks = testHelpers.getFixtures('convert-encoding');
-
-const bindTo = { opt: { encoding: 'utf-8' } };
-test('irc.Client.convertEncoding old', (assert) => {
- const convertEncoding = ((str) => {
- if (self.opt.encoding) {
- const charset = chardet.detect(str);
- return Iconv.encode(Iconv.decode(Buffer.from(str), charset), this.opt.encoding);
- } else {
- return str;
- }
- }).bind(bindTo);
-
- checks.causesException.forEach((line) => {
- let causedException = false;
- try {
- convertEncoding(line);
- } catch (e) {
- causedException = true;
- }
-
- assert.equal(causedException, true, line + ' caused exception');
- });
-
- assert.end();
-});
-
-test('irc.Client.convertEncoding', function(assert) {
- const convertEncoding = irc.Client.prototype.convertEncoding.bind(bindTo);
-
- checks.causesException.forEach((line) => {
- let causedException = false;
-
- try {
- convertEncoding(line);
- } catch (e) {
- causedException = true;
- }
-
- assert.equal(causedException, false, line + ' didn\'t cause exception');
- });
-
- assert.end();
-});
--- /dev/null
+import { Client } from "../src";
+import { describe, test, expect } from "@jest/globals";
+import { convertEncoding as checks } from "./data/fixtures.json";
+
+const bindTo = { opt: { encoding: 'utf-8' } };
+
+describe('Client.convertEncoding', () => {
+ test.each(checks.causesException)("new implementation should not throw with string '%s'", (line) => {
+ const client = new Client('localhost', 'test', { autoConnect: false });
+ const convertEncoding = client.convertEncoding.bind(bindTo);
+ expect(() => convertEncoding(Buffer.from(line))).not.toThrow();
+ });
+});
+
+++ /dev/null
-var net = require('net');
-
-var irc = require('../lib/irc');
-var test = require('tape');
-
-var testHelpers = require('./helpers');
-
-test('sent messages ending with double CRLF', function(t) {
- var mock = testHelpers.MockIrcd();
- var client = new irc.Client('localhost', 'testbot', { debug: true});
-
- var expected = testHelpers.getFixtures('double-CRLF');
-
- t.plan(expected.sent.length + expected.received.length);
-
- mock.server.on('connection', function() {
- mock.send(expected.received[0][0]);
- });
-
- client.on('registered', function() {
- t.equal(mock.outgoing[0], expected.received[0][0], expected.received[0][1]);
- client.disconnect();
- });
-
- mock.on('end', function() {
- var msgs = mock.getIncomingMsgs();
-
- for (var i = 0; i < msgs.length; i++) {
- t.equal(msgs[i], expected.sent[i][0], expected.sent[i][1]);
- }
- mock.close();
- });
-});
--- /dev/null
+
+import { MockIrcd } from './helpers';
+import { Client } from "../src";
+import { test, expect } from "@jest/globals";
+import { doubleCRLF as doubleCRLFFixture } from "./data/fixtures.json";
+
+test('sent messages ending with double CRLF', async () => {
+ const mock = new MockIrcd();
+ const port = await mock.listen();
+ const client = new Client('localhost', 'testbot', { debug: true, port });
+
+ const expected = doubleCRLFFixture;
+
+ mock.server.on('connection', function() {
+ mock.send(expected.received[0][0]);
+ });
+
+ client.on('registered', function() {
+ expect(mock.outgoing[0]).toEqual(expected.received[0][0]);
+ client.disconnect();
+ });
+
+ mock.on('end', function() {
+ const msgs = mock.getIncomingMsgs();
+
+ for (let i = 0; i < msgs.length; i++) {
+ expect(msgs[i]).toEqual(expected.sent[i][0]);
+ }
+ mock.close();
+
+ expect.assertions(expected.sent.length + expected.received.length);
+ });
+});
+++ /dev/null
-var net = require('net');
-
-var irc = require('../lib/irc');
-var test = require('tape');
-
-var testHelpers = require('./helpers');
-
-var expected = testHelpers.getFixtures('basic');
-var greeting = ':localhost 001 testbot :Welcome to the Internet Relay Chat Network testbot\r\n';
-
-test('connect, register and quit', function(t) {
- runTests(t, false, false);
-});
-
-test('connect, register and quit, securely', function(t) {
- runTests(t, true, false);
-});
-
-test('connect, register and quit, securely, with secure object', function(t) {
- runTests(t, true, true);
-});
-
-function runTests(t, isSecure, useSecureObject) {
- const port = isSecure ? 6697 : 6667;
- const mock = testHelpers.MockIrcd(port, 'utf-8', isSecure);
- let client;
- if (isSecure) {
- client = new irc.Client( useSecureObject ? 'notlocalhost' : 'localhost', 'testbot', {
- secure: useSecureObject ? {
- host: 'localhost',
- port: port,
- rejectUnauthorized: false
- } : true,
- port,
- selfSigned: true,
- retryCount: 0,
- debug: true
- });
- } else {
- client = new irc.Client('localhost', 'testbot', {
- secure: isSecure,
- selfSigned: true,
- port: port,
- retryCount: 0,
- debug: true
- });
- }
-
- t.plan(expected.sent.length + expected.received.length);
-
- mock.server.on(isSecure ? 'secureConnection' : 'connection', function() {
- mock.send(greeting);
- });
-
- client.on('registered', function() {
- t.equal(mock.outgoing[0], expected.received[0][0], expected.received[0][1]);
- client.disconnect();
- });
-
- mock.on('end', function() {
- const msgs = mock.getIncomingMsgs();
-
- for (var i = 0; i < msgs.length; i++) {
- t.equal(msgs[i], expected.sent[i][0], expected.sent[i][1]);
- }
- mock.close();
- });
-}
\ No newline at end of file
--- /dev/null
+import { Client } from "../src";
+import { MockIrcd } from "./helpers";
+import { basic as expected } from "./data/fixtures.json";
+import { describe, test, expect } from "@jest/globals";
+
+const greeting = ':localhost 001 testbot :Welcome to the Internet Relay Chat Network testbot\r\n';
+
+
+describe('IRC client basics', () => {
+ test.each([
+ ['connect, register and quit', false, false],
+ ['connect, register and quit, securely', true, false],
+ ['connect, register and quit, securely, with secure object', true, true],
+ ])('%s', async (_name, isSecure, useSecureObject) => {
+ const mock = new MockIrcd("utf-8", isSecure);
+ const port = await mock.listen();
+ let client: Client;
+ if (isSecure) {
+ client = new Client( useSecureObject ? 'notlocalhost' : 'localhost', 'testbot', {
+ secure: useSecureObject ? {
+ host: 'localhost',
+ port: port,
+ rejectUnauthorized: false
+ } : true,
+ port,
+ selfSigned: true,
+ retryCount: 0,
+ debug: true
+ });
+ }
+ else {
+ client = new Client('localhost', 'testbot', {
+ secure: isSecure,
+ selfSigned: true,
+ port: port,
+ retryCount: 0,
+ debug: true
+ });
+ }
+
+ mock.server.on(isSecure ? 'secureConnection' : 'connection', function() {
+ mock.send(greeting);
+ });
+
+ client.on('registered', function() {
+ expect(mock.outgoing[0]).toEqual(expected.received[0][0]);
+ client.disconnect();
+ });
+
+ mock.on('end', function() {
+ const msgs = mock.getIncomingMsgs();
+
+ for (let i = 0; i < msgs.length; i++) {
+ expect(msgs[i]).toEqual(expected.sent[i][0]);
+ }
+ mock.close();
+
+ expect.assertions(expected.sent.length + expected.received.length);
+ });
+ })
+});
import { describe, test, expect } from "@jest/globals";
describe('parseMessage', () => {
- Object.entries(parseline).forEach(([line, resultWithOpts]) =>
- test(`can parse '${line}'`, () => {
- const result: typeof resultWithOpts&{stripColors?: boolean} = resultWithOpts;
- let stripColors = false;
- if ('stripColors' in result) {
- stripColors = result.stripColors ?? false;
- delete result.stripColors;
- }
+ test.each(
+ Object.entries(parseline)
+ )("can parse '%s'", (line, resultWithOpts) => {
+ const result: typeof resultWithOpts&{stripColors?: boolean} = resultWithOpts;
+ let stripColors = false;
+ if ('stripColors' in result) {
+ stripColors = result.stripColors ?? false;
+ delete result.stripColors;
+ }
- expect(
- parseMessage(line, stripColors)
- ).toEqual(
- result
- );
- })
- );
+ expect(
+ parseMessage(line, stripColors)
+ ).toEqual(
+ result
+ );
+ });
});