import * as os from 'os'; import {Page} from 'puppeteer'; import axios from 'axios'; import * as auth from './authentication'; import * as selector from './selector'; import {GotifyTest, newTest, newPluginDir} from './setup'; import {innerText, waitForCount, waitForExists} from './utils'; const pluginSupported = ['linux', 'darwin'].indexOf(os.platform()) !== -1; let page: Page; let gotify: GotifyTest; beforeAll(async () => { const gotifyPluginDir = pluginSupported ? await newPluginDir(['github.com/gotify/server/v2/plugin/example/echo']) : ''; gotify = await newTest(gotifyPluginDir); page = gotify.page; }); afterAll(async () => await gotify.close()); enum Col { ID = 1, SetEnabled = 2, Name = 3, Token = 4, Details = 5, } const hiddenToken = '•••••••••••••••'; const $table = selector.table('#plugin-table'); const switchSelctor = (id: number) => $table.cell(id, Col.SetEnabled, '[data-enabled]'); const enabledState = async (id: number) => (await page.$eval(switchSelctor(id), (el) => el.getAttribute('data-enabled'))) === 'true'; const toggleEnabled = async (id: number) => { const origEnabled = (await enabledState(id)).toString(); await page.click(switchSelctor(id)); await page.waitForFunction( `document.querySelector("${switchSelctor( id )}").getAttribute("data-enabled") !== "${origEnabled}"` ); }; const pluginInfo = async (className: string) => { return await innerText(page, `.plugin-info .${className} > span`); }; const getDisplayer = async () => { return await innerText(page, '.displayer'); }; const hasReceivedMessage = async (title: RegExp, content: RegExp) => { await page.click('#message-navigation a'); await waitForExists(page, selector.heading(), 'All Messages'); expect(await innerText(page, '.title')).toMatch(title); expect(await innerText(page, '.content')).toMatch(content); await page.click('#navigate-plugins'); await waitForExists(page, selector.heading(), 'Plugins'); }; const inDetailPage = async (id: number, callback: () => Promise) => { const name = await innerText(page, $table.cell(id, Col.Name)); await page.click($table.cell(id, Col.Details, 'button')); await waitForExists(page, '.plugin-info .name > span', name); await callback(); await page.click('#navigate-plugins'); await waitForExists(page, selector.heading(), 'Plugins'); await page.waitForSelector($table.selector()); }; describe('plugin', () => { describe('navigation', () => { it('does login', async () => await auth.login(page)); it('navigates to plugins', async () => { await page.click('#navigate-plugins'); await waitForExists(page, selector.heading(), 'Plugins'); }); }); if (!pluginSupported) { return; } describe('functionality test', () => { describe('initial status', () => { it('has echo plugin', async () => { await waitForCount(page, $table.rows(), 1); expect(await innerText(page, $table.cell(1, Col.Name))).toEqual('test plugin'); expect(await innerText(page, $table.cell(1, Col.Token))).toBe(hiddenToken); expect(parseInt(await innerText(page, $table.cell(1, Col.ID)), 10)).toBeGreaterThan( 0 ); }); it('is disabled by default', async () => { expect(await enabledState(1)).toBe(false); }); }); describe('enable and disable plugin', () => { it('enable', async () => { await toggleEnabled(1); expect(await enabledState(1)).toBe(true); }); it('disable', async () => { await toggleEnabled(1); expect(await enabledState(1)).toBe(false); }); }); describe('details page', () => { it('has plugin info', async () => { await inDetailPage(1, async () => { expect(await pluginInfo('module-path')).toBe( 'github.com/gotify/server/v2/plugin/example/echo' ); }); }); it('has displayer', async () => { await inDetailPage(1, async () => { expect(await getDisplayer()).toBeTruthy(); }); }); it('has configurer', async () => { await inDetailPage(1, async () => { expect(await page.$('.configurer')).toBeTruthy(); }); }); it('updates configurer', async () => { await inDetailPage(1, async () => { expect( await ( await (await page.$('.config-save'))!.getProperty('disabled') ).jsonValue() ).toBe(true); await page.waitForSelector('.CodeMirror .CodeMirror-code'); await page.waitForFunction( 'document.querySelector(".CodeMirror .CodeMirror-code").innerText.toLowerCase().indexOf("loading")<0' ); await page.click('.CodeMirror .CodeMirror-code > div'); await page.keyboard.press('x'); await page.waitForFunction( 'document.querySelector(".config-save") && !document.querySelector(".config-save").disabled' ); await page.click('.config-save'); await page.waitForFunction('document.querySelector(".config-save").disabled'); }); }); it('configurer updated', async () => { await inDetailPage(1, async () => { expect( await ( await (await page.$('.config-save'))!.getProperty('disabled') ).jsonValue() ).toBe(true); await page.waitForSelector('.CodeMirror .CodeMirror-code > div'); await page.waitForFunction( 'document.querySelector(".CodeMirror .CodeMirror-code > div").innerText.toLowerCase().indexOf("loading")<0' ); expect(await innerText(page, '.CodeMirror .CodeMirror-code > div')).toMatch( /x$/ ); }); }); it('sends messages', async () => { if (!(await enabledState(1))) { await toggleEnabled(1); } await inDetailPage(1, async () => { const hook = await page.$eval('.displayer a', (el) => el.getAttribute('href')); await axios.get(hook!); }); }); it('has received message', async () => { await hasReceivedMessage( /^.+received$/, /^echo server received a hello message \d+ times$/ ); }); }); }); });