// eslint-disable-next-line @typescript-eslint/no-var-requires, no-undef
const puppeteer = require('puppeteer');
// eslint-disable-next-line @typescript-eslint/no-var-requires, no-undef
const waitForExpect = require('wait-for-expect');


describe('RTCPushMessage 3 browsers', () => {
    var b1, b2, b3;
    var p1, p2, p3;


    beforeEach(async () => {
        b1 = await puppeteer.launch({ headless: false });
        //grant notification permission
        await b1.defaultBrowserContext().overridePermissions('http://localhost:3000', ['notifications']);

        b2 = await puppeteer.launch({ headless: false });
        //grant notification permission
        await b2.defaultBrowserContext().overridePermissions('http://127.0.0.1:3000', ['notifications']);

        b3 = await puppeteer.launch({ headless: false });
        //grant notification permission
        await b3.defaultBrowserContext().overridePermissions('http://localhost:3000', ['notifications']);

        p1 = await b1.newPage();
        await p1.goto('http://localhost:3000/test/');

        p2 = await b2.newPage();
        await p2.goto('http://127.0.0.1:3000/test/');

        p3 = await b3.newPage();
        await p3.goto('http://localhost:3000/test/');
    }, 30000);

    it('should be able to send messages to multiple endpoints at once', async () => {
        const p1Address = await p1.evaluate(() => window.tests.getOwnAddress());
        const p2Address = await p2.evaluate(() => window.tests.getOwnAddress());
        const p3Address = await p3.evaluate(() => window.tests.getOwnAddress());
        const p1Parsed = JSON.parse(p1Address);
        const p2Parsed = JSON.parse(p2Address);
        const p3Parsed = JSON.parse(p3Address);
        await p1.evaluate((a) => window.tests.addContact(a), p2Address);
        await p2.evaluate((a) => window.tests.addContact(a), p1Address);
        await p1.evaluate((a) => window.tests.addContact(a), p3Address);
        await p3.evaluate((a) => window.tests.addContact(a), p1Address);

        const p1Callback = jest.fn();
        const p2Callback = jest.fn();
        const p3Callback = jest.fn();

        //recieving a message will call our mock callback
        p1.evaluate(() => window.tests.waitForMessage(2)).then(p1Callback);
        p2.evaluate(() => window.tests.waitForMessage()).then(p2Callback);
        p3.evaluate(() => window.tests.waitForMessage()).then(p3Callback);

        //send the message to the other browser (p1 -> p2)
        await p1.evaluate((add, msg) => window.tests.sendMessage(add, msg), p2Parsed.userId, 'hello2');
        //send the message to the other browser (p1 -> p3)
        await p1.evaluate((add, msg) => window.tests.sendMessage(add, msg), p3Parsed.userId, 'hello3');
        //send the message to the other browser (p2 -> p1)
        await p2.evaluate((add, msg) => window.tests.sendMessage(add, msg), p1Parsed.userId, 'hello12');
        //send the message to the other browser (p3 -> p1)
        await p3.evaluate((add, msg) => window.tests.sendMessage(add, msg), p1Parsed.userId, 'hello13');
        await waitForExpect(() => {
            expect(p1Callback.mock.calls.length).toBe(1);
            expect(p2Callback.mock.calls.length).toBe(1);
            expect(p3Callback.mock.calls.length).toBe(1);
        }, 50000);
        expect(p1Callback.mock.calls[0][0]).toEqual([{ from: p2Parsed.userId, msg: 'hello12' }, { from: p3Parsed.userId, msg: 'hello13' }]);
        expect(p2Callback.mock.calls[0][0]).toEqual({ from: p1Parsed.userId, msg: 'hello2' });
        expect(p3Callback.mock.calls[0][0]).toEqual({ from: p1Parsed.userId, msg: 'hello3' });
    }, 60000);

    afterEach(async () => {
        b1.close();
        b2.close();
        b3.close();
    });
});