]> jfr.im git - irc/evilnet/node-irc-nefarious.git/commitdiff
Fix tests
authorHalf-Shot <redacted>
Thu, 27 Jul 2023 16:29:25 +0000 (17:29 +0100)
committerHalf-Shot <redacted>
Thu, 27 Jul 2023 16:29:25 +0000 (17:29 +0100)
spec/client.spec.ts
src/irc.ts
src/testing/index.ts

index 337125d790013342b41ae95c436717f3930bd212..eda92ce7210d66ccb9c6c5cba7b68f0abdfdbde0 100644 (file)
@@ -1,5 +1,6 @@
 import { describe, beforeEach, afterEach, expect, test } from '@jest/globals';
 import { TestIrcServer } from '../src/testing';
+import { IrcSupported } from '../src';
 
 describe('Client', () => {
     let server: TestIrcServer;
@@ -13,114 +14,123 @@ describe('Client', () => {
     describe('joining channels', () => {
         test('will get a join event from a newly joined user', async () => {
             const { speaker, listener } = server.clients;
+            const expectedChannel = TestIrcServer.generateUniqueChannel('foobar');
 
             // Join the room and listen
             const listenerJoinPromise = listener.waitForEvent('join');
-            await listener.join('#foobar');
+            await listener.join(expectedChannel);
             const [lChannel, lNick] = await listenerJoinPromise;
             expect(lNick).toBe(listener.nick);
-            expect(lChannel).toBe('#foobar');
+            expect(lChannel).toBe(expectedChannel);
 
             const speakerJoinPromise = listener.waitForEvent('join');
-            await speaker.join('#foobar');
+            await speaker.join(expectedChannel);
             const [channel, nick] = await speakerJoinPromise;
             expect(nick).toBe(speaker.nick);
-            expect(channel).toBe('#foobar');
+            expect(channel).toBe(expectedChannel);
         });
         test('can join a channel and send a message', async () => {
             const { speaker, listener } = server.clients;
-            await listener.join('#foobar');
+            const expectedChannel = TestIrcServer.generateUniqueChannel('foobar');
+            await listener.join(expectedChannel);
             const messagePromise = listener.waitForEvent('message');
-            await speaker.join('#foobar');
-            await speaker.say('#foobar', 'Hello world!');
+            await speaker.join(expectedChannel);
+            await speaker.say(expectedChannel, 'Hello world!');
 
             const [nick, channel, text] = await messagePromise;
             expect(nick).toBe(speaker.nick);
-            expect(channel).toBe('#foobar');
+            expect(channel).toBe(expectedChannel);
             expect(text).toBe('Hello world!');
         });
         test('will store channel information', async () => {
             const { speaker } = server.clients;
-            expect(speaker.chanData('#foobar')).toBeUndefined();
-            speaker.join('#foobar');
+            const expectedChannel = TestIrcServer.generateUniqueChannel('foobar');
+            expect(speaker.chanData(expectedChannel)).toBeUndefined();
+            speaker.join(expectedChannel);
             await speaker.waitForEvent('join');
 
-            const channel = speaker.chanData('#foobar');
+            const channel = speaker.chanData(expectedChannel);
             expect(channel).toBeDefined();
-            expect(channel?.key).toEqual('#foobar');
-            expect(channel?.serverName).toEqual('#foobar');
+            expect(channel?.key).toEqual(expectedChannel);
+            expect(channel?.serverName).toEqual(expectedChannel);
             expect(channel?.users.get(speaker.nick)).toBeDefined();
         });
     });
     describe('mode changes', () => {
         test('will handle adding a parameter-less mode', async () => {
             const { speaker } = server.clients;
-            await speaker.join('#foobar');
+            const expectedChannel = TestIrcServer.generateUniqueChannel('foobar');
+            await speaker.join(expectedChannel);
             await speaker.waitForEvent('join');
             const modeEvent = speaker.waitForEvent('+mode');
-            await speaker.send('MODE', '#foobar', '+m');
+            await speaker.send('MODE', expectedChannel, '+m');
 
             const [channel, nick, mode, user] = await modeEvent;
             expect(nick).toBe(speaker.nick);
-            expect(channel).toBe('#foobar');
+            expect(channel).toBe(expectedChannel);
             expect(mode).toBe('m');
             expect(user).toBeUndefined();
         });
         test('will handle removing a parameter-less mode', async () => {
             const { speaker } = server.clients;
-            await speaker.join('#foobar');
+            const expectedChannel = TestIrcServer.generateUniqueChannel('foobar');
+            await speaker.join(expectedChannel);
             await speaker.waitForEvent('join');
             const modeEvent = speaker.waitForEvent('-mode');
-            await speaker.send('MODE', '#foobar', '+m');
-            speaker.send('MODE', '#foobar', '-m');
+            await speaker.send('MODE', expectedChannel, '+m');
+            await speaker.send('MODE', expectedChannel, '-m');
 
             const [channel, nick, mode, user] = await modeEvent;
             expect(nick).toBe(speaker.nick);
-            expect(channel).toBe('#foobar');
+            expect(channel).toBe(expectedChannel);
             expect(mode).toBe('m');
             expect(user).toBeUndefined();
         });
         test('will handle adding a parameter mode', async () => {
             const { speaker, listener } = server.clients;
-            await speaker.join('#foobar');
-            await listener.join('#foobar');
+            const expectedChannel = TestIrcServer.generateUniqueChannel('foobar');
+            await speaker.join(expectedChannel);
+            await listener.join(expectedChannel);
             await speaker.waitForEvent('join');
             const modeEvent = speaker.waitForEvent('+mode');
-            await speaker.send('MODE', '#foobar', '+o', listener.nick);
+            await speaker.send('MODE', expectedChannel, '+o', listener.nick);
 
             const [channel, nick, mode, user] = await modeEvent;
             expect(nick).toBe(speaker.nick);
-            expect(channel).toBe('#foobar');
+            expect(channel).toBe(expectedChannel);
             expect(mode).toBe('o');
             expect(user).toBe(listener.nick);
         });
         test('will handle removing a parameter mode', async () => {
             const { speaker, listener } = server.clients;
-            await speaker.join('#foobar');
-            await listener.join('#foobar');
+            const expectedChannel = TestIrcServer.generateUniqueChannel('foobar');
+            await speaker.join(expectedChannel);
+            await listener.join(expectedChannel);
             await speaker.waitForEvent('join');
-            await speaker.send('MODE', '#foobar', '+o', listener.nick);
+            await speaker.send('MODE', expectedChannel, '+o', listener.nick);
             const modeEvent = speaker.waitForEvent('-mode');
-            await speaker.send('MODE', '#foobar', '-o', listener.nick);
+            await speaker.send('MODE', expectedChannel, '-o', listener.nick);
 
             const [channel, nick, mode, user] = await modeEvent;
             expect(nick).toBe(speaker.nick);
-            expect(channel).toBe('#foobar');
+            expect(channel).toBe(expectedChannel);
             expect(mode).toBe('o');
             expect(user).toBe(listener.nick);
         });
     });
-    describe('joining channels', () => {
-        test('will get a join event from a newly joined user', async () => {
+    describe('isupport', () => {
+        test('will not duplicate isupport values', async () => {
             const { speaker } = server.clients;
-            const iSupportOriginal = JSON.parse(JSON.stringify(speaker.supported));
             // We assume the original isupport has arrived by this point.
             const isupportEventPromise = speaker.waitForEvent('isupport');
             await speaker.send('VERSION');
             await isupportEventPromise;
 
-            const iSupportNew = JSON.parse(JSON.stringify(speaker.supported));
-            expect(iSupportNew).toEqual(iSupportOriginal);
+            expect(speaker.supported.channel.modes.a).toHaveLength(new Set(speaker.supported.channel.modes.a).size)
+            expect(speaker.supported.channel.modes.b).toHaveLength(new Set(speaker.supported.channel.modes.b).size)
+            expect(speaker.supported.channel.modes.c).toHaveLength(new Set(speaker.supported.channel.modes.c).size)
+            expect(speaker.supported.channel.modes.d).toHaveLength(new Set(speaker.supported.channel.modes.d).size)
+            expect(speaker.supported.extra).toHaveLength(new Set(speaker.supported.extra).size);
         });
     });
 });
index 135933aed1eee362af24fcdf169285b3d11a314f..40c85898b83efb8a845adae2393be6e115da1b69 100644 (file)
@@ -355,14 +355,7 @@ export class Client extends (EventEmitter as unknown as new () => TypedEmitter<C
     }
 
     private onReplyISupport(message: Message) {
-
-        // Clear extras
-        this.state.supportedState.extra = [];
         // Clear modes
-        this.state.supportedState.channel.modes = {
-            a:'', b:'', c:'', d:''
-        };
-
         message.args.forEach((arg) => {
             let match;
             match = arg.match(/([A-Z]+)=(.*)/);
@@ -387,7 +380,12 @@ export class Client extends (EventEmitter as unknown as new () => TypedEmitter<C
                     const values = value.split(',');
                     const type: ['a', 'b', 'c', 'd'] = ['a', 'b', 'c', 'd'];
                     for (let i = 0; i < type.length; i++) {
-                        this.state.supportedState.channel.modes[type[i]] += values[i];
+                        // Note, we don't detect removed modes here.
+                        // But we don't expect that to happen to a connection.
+                        const mode = values[i];
+                        if (!this.state.supportedState.channel.modes[type[i]].includes(mode)) {
+                            this.state.supportedState.channel.modes[type[i]] += mode;
+                        }
                     }
                     break;
                 }
@@ -423,7 +421,9 @@ export class Client extends (EventEmitter as unknown as new () => TypedEmitter<C
                         const match2 = match[2].split('');
                         while (match1.length) {
                             this.state.modeForPrefix[match2[0]] = match1[0];
-                            this.state.supportedState.channel.modes.b += match1[0];
+                            if (!this.state.supportedState.channel.modes.b.includes(match1[0])) {
+                                this.state.supportedState.channel.modes.b += match1[0];
+                            }
                             const idx = match1.shift();
                             if (idx) {
                                 const result = match2.shift();
@@ -451,7 +451,9 @@ export class Client extends (EventEmitter as unknown as new () => TypedEmitter<C
                     this.state.supportedState.topiclength = parseInt(value);
                     break;
                 default:
-                    this.state.supportedState.extra.push(value);
+                    if (!this.state.supportedState.extra.includes(value)) {
+                        this.state.supportedState.extra.push(value);
+                    }
                     break;
             }
         });
index 2266a4ff799ff405bc23c02c47d73b8bb9da8f85..81a777fd076c53f2b7c3e9f675a9478a6297d977 100644 (file)
@@ -70,6 +70,9 @@ export class TestIrcServer {
     static generateUniqueNick(name = 'default') {
         return `${name}-${randomUUID().replace('-', '').substring(0, 8)}`;
     }
+    static generateUniqueChannel(name = 'default') {
+        return `#${this.generateUniqueNick(name)}`;
+    }
 
     public readonly clients: Record<string, TestClient> = {};
     constructor(public readonly address = DEFAULT_ADDRESS, public readonly port = DEFAULT_PORT) { }
@@ -82,6 +85,7 @@ export class TestIrcServer {
                     port: this.port,
                     autoConnect: false,
                     connectionTimeout: 4000,
+                    debug: true,
                 });
             this.clients[clientName] = client;
             // Make sure we load isupport before reporting readyness.