# Conflicts: # src/components/notifications/SMTP.vue # src/languages/en.jspull/451/head
commit
c8706b9aa1
@ -0,0 +1,34 @@
|
|||||||
|
# This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node
|
||||||
|
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
||||||
|
|
||||||
|
name: Auto Test
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
node-version: [14.x, 15.x, 16.x]
|
||||||
|
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
|
uses: actions/setup-node@v2
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
cache: 'npm'
|
||||||
|
- run: npm ci
|
||||||
|
- run: npm run build
|
||||||
|
- run: npm test
|
||||||
|
env:
|
||||||
|
HEADLESS_TEST: 1
|
||||||
|
JUST_FOR_TEST: ${{ secrets.JUST_FOR_TEST }}
|
@ -0,0 +1,6 @@
|
|||||||
|
module.exports = {
|
||||||
|
"launch": {
|
||||||
|
"headless": process.env.HEADLESS_TEST || false,
|
||||||
|
"userDataDir": "./data/test-chrome-profile",
|
||||||
|
}
|
||||||
|
};
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,52 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h4>{{ $t("Certificate Info") }}</h4>
|
||||||
|
{{ $t("Certificate Chain") }}:
|
||||||
|
<div
|
||||||
|
v-if="valid"
|
||||||
|
class="rounded d-inline-flex ms-2 text-white tag-valid"
|
||||||
|
>
|
||||||
|
{{ $t("Valid") }}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="!valid"
|
||||||
|
class="rounded d-inline-flex ms-2 text-white tag-invalid"
|
||||||
|
>
|
||||||
|
{{ $t("Invalid") }}
|
||||||
|
</div>
|
||||||
|
<certificate-info-row :cert="certInfo" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import CertificateInfoRow from "./CertificateInfoRow.vue";
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
CertificateInfoRow,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
certInfo: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
valid: {
|
||||||
|
type: Boolean,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "../assets/vars.scss";
|
||||||
|
|
||||||
|
.tag-valid {
|
||||||
|
padding: 2px 25px;
|
||||||
|
background-color: $primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-invalid {
|
||||||
|
padding: 2px 25px;
|
||||||
|
background-color: $danger;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,122 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="d-flex flex-row align-items-center p-1 overflow-hidden">
|
||||||
|
<div class="m-3 ps-3">
|
||||||
|
<div class="cert-icon">
|
||||||
|
<font-awesome-icon icon="file" />
|
||||||
|
<font-awesome-icon class="award-icon" icon="award" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="m-3">
|
||||||
|
<table class="text-start">
|
||||||
|
<tbody>
|
||||||
|
<tr class="my-3">
|
||||||
|
<td class="px-3">Subject:</td>
|
||||||
|
<td>{{ formatSubject(cert.subject) }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="my-3">
|
||||||
|
<td class="px-3">Valid To:</td>
|
||||||
|
<td><Datetime :value="cert.validTo" /></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="my-3">
|
||||||
|
<td class="px-3">Days Remaining:</td>
|
||||||
|
<td>{{ cert.daysRemaining }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="my-3">
|
||||||
|
<td class="px-3">Issuer:</td>
|
||||||
|
<td>{{ formatSubject(cert.issuer) }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="my-3">
|
||||||
|
<td class="px-3">Fingerprint:</td>
|
||||||
|
<td>{{ cert.fingerprint }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex">
|
||||||
|
<font-awesome-icon
|
||||||
|
v-if="cert.issuerCertificate"
|
||||||
|
class="m-2 ps-6 link-icon"
|
||||||
|
icon="link"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<certificate-info-row
|
||||||
|
v-if="cert.issuerCertificate"
|
||||||
|
:cert="cert.issuerCertificate"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Datetime from "../components/Datetime.vue";
|
||||||
|
export default {
|
||||||
|
name: "CertificateInfoRow",
|
||||||
|
components: {
|
||||||
|
Datetime,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
cert: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
formatSubject(subject) {
|
||||||
|
if (subject.O && subject.CN && subject.C) {
|
||||||
|
return `${subject.CN} - ${subject.O} (${subject.C})`;
|
||||||
|
} else if (subject.O && subject.CN) {
|
||||||
|
return `${subject.CN} - ${subject.O}`;
|
||||||
|
} else if (subject.CN) {
|
||||||
|
return subject.CN;
|
||||||
|
} else {
|
||||||
|
return "no info";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "../assets/vars.scss";
|
||||||
|
|
||||||
|
table {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cert-icon {
|
||||||
|
position: relative;
|
||||||
|
font-size: 70px;
|
||||||
|
color: $link-color;
|
||||||
|
opacity: 0.5;
|
||||||
|
|
||||||
|
.dark & {
|
||||||
|
color: $dark-font-color;
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.award-icon {
|
||||||
|
position: absolute;
|
||||||
|
font-size: 0.5em;
|
||||||
|
bottom: 20%;
|
||||||
|
left: 12%;
|
||||||
|
color: white;
|
||||||
|
|
||||||
|
.dark & {
|
||||||
|
color: $dark-bg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-icon {
|
||||||
|
font-size: 20px;
|
||||||
|
margin-left: 50px !important;
|
||||||
|
color: $link-color;
|
||||||
|
opacity: 0.5;
|
||||||
|
|
||||||
|
.dark & {
|
||||||
|
color: $dark-font-color;
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,199 @@
|
|||||||
|
export default {
|
||||||
|
languageName: "Magyar",
|
||||||
|
checkEverySecond: "Ellenőrzés {0} másodpercenként",
|
||||||
|
retryCheckEverySecond: "Újrapróbál {0} másodpercenként.",
|
||||||
|
retriesDescription: "Maximális próbálkozás mielőtt a szolgáltatás leállt jelőlést kap és értesítés kerül kiküldésre",
|
||||||
|
ignoreTLSError: "TLS/SSL hibák figyelnen kívül hagyása HTTPS weboldalaknál",
|
||||||
|
upsideDownModeDescription: "Az állapot megfordítása. Ha a szolgáltatás elérhető, akkor lesz leállt állapotú.",
|
||||||
|
maxRedirectDescription: "Az átirányítások maximális száma. állítsa 0-ra az átirányítás tiltásához.",
|
||||||
|
acceptedStatusCodesDescription: "Válassza ki az állapot kódokat amelyek sikeres válasznak fognak számítani.",
|
||||||
|
passwordNotMatchMsg: "A megismételt jelszó nem egyezik.",
|
||||||
|
notificationDescription: "Kérem, rendeljen egy értesítést a figyeléshez, hogy működjön.",
|
||||||
|
keywordDescription: "Kulcsszó keresése a html-ben vagy a JSON válaszban. (kis-nagybetű érzékeny)",
|
||||||
|
pauseDashboardHome: "Szünetel",
|
||||||
|
deleteMonitorMsg: "Biztos, hogy törölni akarja ezt a figyelőt?",
|
||||||
|
deleteNotificationMsg: "Biztos, hogy törölni akarja ezt az értesítést az összes figyelőnél?",
|
||||||
|
resoverserverDescription: "A Cloudflare az alapértelmezett szerver, bármikor meg tudja változtatni a resolver server-t.",
|
||||||
|
rrtypeDescription: "Válassza ki az RR-Típust a figyelőhöz",
|
||||||
|
pauseMonitorMsg: "Biztos, hogy szüneteltetni akarja?",
|
||||||
|
enableDefaultNotificationDescription: "Minden új figyelőhöz ez az értesítés engedélyezett lesz alapértelmezetten. Kikapcsolhatja az értesítést külön minden figyelőnél.",
|
||||||
|
clearEventsMsg: "Biztos, hogy törölni akar miden eseményt ennél a figyelnél?",
|
||||||
|
clearHeartbeatsMsg: "Biztos, hogy törölni akar minden heartbeat-et ennél a figyelőnél?",
|
||||||
|
confirmClearStatisticsMsg: "Biztos, hogy törölni akat MINDEN statisztikát?",
|
||||||
|
importHandleDescription: "Válassza a 'Meglévő kihagyását', ha ki szeretné hagyni az azonos nevő figyelőket vagy értesítésket. A 'Felülírás' törölni fog minden meglévő figyelőt és értesítést.",
|
||||||
|
confirmImportMsg: "Biztos, hogy importálja a mentést? Győzödjön meg róla, hogy jól választotta ki az importálás opciót.",
|
||||||
|
twoFAVerifyLabel: "Kérem, adja meg a token-t, hogy a 2FA működését ellenőrizzük",
|
||||||
|
tokenValidSettingsMsg: "A token érvényes! El tudja menteni a 2FA beállításait.",
|
||||||
|
confirmEnableTwoFAMsg: "Biztosan engedélyezi a 2FA-t?",
|
||||||
|
confirmDisableTwoFAMsg: "Biztosan letiltja a 2FA-t?",
|
||||||
|
Settings: "Beállítások",
|
||||||
|
Dashboard: "Irányítópult",
|
||||||
|
"New Update": "Új frissítés",
|
||||||
|
Language: "Nyelv",
|
||||||
|
Appearance: "Megjelenés",
|
||||||
|
Theme: "Téma",
|
||||||
|
General: "Általános",
|
||||||
|
Version: "Verzió",
|
||||||
|
"Check Update On GitHub": "Frissítések keresése a GitHub-on",
|
||||||
|
List: "Lista",
|
||||||
|
Add: "Hozzáadás",
|
||||||
|
"Add New Monitor": "Új figyelő hozzáadása",
|
||||||
|
"Quick Stats": "Gyors statisztikák",
|
||||||
|
Up: "Működik",
|
||||||
|
Down: "Leállt",
|
||||||
|
Pending: "Függőben",
|
||||||
|
Unknown: "Ismeretlen",
|
||||||
|
Pause: "Szünet",
|
||||||
|
Name: "Név",
|
||||||
|
Status: "Állapot",
|
||||||
|
DateTime: "Időpont",
|
||||||
|
Message: "Üzenet",
|
||||||
|
"No important events": "Nincs fontos esemény",
|
||||||
|
Resume: "Folytatás",
|
||||||
|
Edit: "Szerkesztés",
|
||||||
|
Delete: "Törlés",
|
||||||
|
Current: "Aktuális",
|
||||||
|
Uptime: "Uptime",
|
||||||
|
"Cert Exp.": "Tanúsítvány lejár",
|
||||||
|
days: "napok",
|
||||||
|
day: "nap",
|
||||||
|
"-day": "-nap",
|
||||||
|
hour: "óra",
|
||||||
|
"-hour": "-óra",
|
||||||
|
Response: "Válasz",
|
||||||
|
Ping: "Ping",
|
||||||
|
"Monitor Type": "Figyelő típusa",
|
||||||
|
Keyword: "Kulcsszó",
|
||||||
|
"Friendly Name": "Rövid név",
|
||||||
|
URL: "URL",
|
||||||
|
Hostname: "Hostnév",
|
||||||
|
Port: "Port",
|
||||||
|
"Heartbeat Interval": "Heartbeat időköz",
|
||||||
|
Retries: "Újrapróbálkozás",
|
||||||
|
"Heartbeat Retry Interval": "Heartbeat újrapróbálkozások időköze",
|
||||||
|
Advanced: "Haladó",
|
||||||
|
"Upside Down Mode": "Fordított mód",
|
||||||
|
"Max. Redirects": "Max. átirányítás",
|
||||||
|
"Accepted Status Codes": "Elfogadott állapot kódok",
|
||||||
|
Save: "Mentés",
|
||||||
|
Notifications: "Értesítések",
|
||||||
|
"Not available, please setup.": "Nem elérhető, állítsa be.",
|
||||||
|
"Setup Notification": "Értesítés beállítása",
|
||||||
|
Light: "Világos",
|
||||||
|
Dark: "Sötét",
|
||||||
|
Auto: "Auto",
|
||||||
|
"Theme - Heartbeat Bar": "Téma - Heartbeat Bar",
|
||||||
|
Normal: "Normal",
|
||||||
|
Bottom: "Nyomógomb",
|
||||||
|
None: "Nincs",
|
||||||
|
Timezone: "Időzóna",
|
||||||
|
"Search Engine Visibility": "Látható a keresőmotoroknak",
|
||||||
|
"Allow indexing": "Indexelés engedélyezése",
|
||||||
|
"Discourage search engines from indexing site": "Keresőmotorok elriasztása az oldal indexelésétől",
|
||||||
|
"Change Password": "Jelszó változtatása",
|
||||||
|
"Current Password": "Jelenlegi jelszó",
|
||||||
|
"New Password": "Új jelszó",
|
||||||
|
"Repeat New Password": "Ismételje meg az új jelszót",
|
||||||
|
"Update Password": "Jelszó módosítása",
|
||||||
|
"Disable Auth": "Hitelesítés tiltása",
|
||||||
|
"Enable Auth": "Hitelesítés engedélyezése",
|
||||||
|
Logout: "Kijelenetkezés",
|
||||||
|
Leave: "Elhagy",
|
||||||
|
"I understand, please disable": "Megértettem, kérem tilsa le",
|
||||||
|
Confirm: "Megerősítés",
|
||||||
|
Yes: "Igen",
|
||||||
|
No: "Nem",
|
||||||
|
Username: "Felhasználónév",
|
||||||
|
Password: "Jelszó",
|
||||||
|
"Remember me": "Emlékezzen rám",
|
||||||
|
Login: "Bejelentkezés",
|
||||||
|
"No Monitors, please": "Nincs figyelő, kérem",
|
||||||
|
"add one": "adjon hozzá egyet",
|
||||||
|
"Notification Type": "Értesítés típusa",
|
||||||
|
Email: "Email",
|
||||||
|
Test: "Teszt",
|
||||||
|
"Certificate Info": "Tanúsítvány információk",
|
||||||
|
"Resolver Server": "Resolver szerver",
|
||||||
|
"Resource Record Type": "Resource Record típusa",
|
||||||
|
"Last Result": "Utolsó eredmény",
|
||||||
|
"Create your admin account": "Hozza létre az adminisztrátor felhasználót",
|
||||||
|
"Repeat Password": "Jelszó ismétlése",
|
||||||
|
"Import Backup": "Mentés importálása",
|
||||||
|
"Export Backup": "Mentés exportálása",
|
||||||
|
Export: "Exportálás",
|
||||||
|
Import: "Importálás",
|
||||||
|
respTime: "Válaszidő (ms)",
|
||||||
|
notAvailableShort: "N/A",
|
||||||
|
"Default enabled": "Alapértelmezetten engedélyezett",
|
||||||
|
"Apply on all existing monitors": "Alkalmazza az összes figyelőre",
|
||||||
|
Create: "Létrehozás",
|
||||||
|
"Clear Data": "Adatok törlése",
|
||||||
|
Events: "Események",
|
||||||
|
Heartbeats: "Heartbeats",
|
||||||
|
"Auto Get": "Auto Get",
|
||||||
|
backupDescription: "Ki tudja menteni az összes figyelőt és értesítést egy JSON fájlba.",
|
||||||
|
backupDescription2: "Ui.: Történeti és esemény adatokat nem tartalmaz.",
|
||||||
|
backupDescription3: "Érzékeny adatok, pl. szolgáltatás kulcsok is vannak az export fájlban. Figyelmesen őrizze!",
|
||||||
|
alertNoFile: "Válaszzon ki egy fájlt az importáláshoz.",
|
||||||
|
alertWrongFileType: "Válasszon egy JSON fájlt.",
|
||||||
|
"Clear all statistics": "Összes statisztika törlése",
|
||||||
|
"Skip existing": "Meglévő kihagyása",
|
||||||
|
Overwrite: "Felülírás",
|
||||||
|
Options: "Opciók",
|
||||||
|
"Keep both": "Mindegyiket tartsa meg",
|
||||||
|
"Verify Token": "Token ellenőrzése",
|
||||||
|
"Setup 2FA": "2FA beállítása",
|
||||||
|
"Enable 2FA": "2FA engedélyezése",
|
||||||
|
"Disable 2FA": "2FA toltása",
|
||||||
|
"2FA Settings": "2FA beállítások",
|
||||||
|
"Two Factor Authentication": "Two Factor Authentication",
|
||||||
|
Active: "Aktív",
|
||||||
|
Inactive: "Inaktív",
|
||||||
|
Token: "Token",
|
||||||
|
"Show URI": "URI megmutatása",
|
||||||
|
Tags: "Cimkék",
|
||||||
|
"Add New below or Select...": "Adjon hozzá lentre vagy válasszon...",
|
||||||
|
"Tag with this name already exist.": "Ilyen nevű cimke már létezik.",
|
||||||
|
"Tag with this value already exist.": "Ilyen értékű cimke már létezik.",
|
||||||
|
color: "szín",
|
||||||
|
"value (optional)": "érték (opcionális)",
|
||||||
|
Gray: "Szürke",
|
||||||
|
Red: "Piros",
|
||||||
|
Orange: "Narancs",
|
||||||
|
Green: "Zöld",
|
||||||
|
Blue: "Kék",
|
||||||
|
Indigo: "Indigó",
|
||||||
|
Purple: "Lila",
|
||||||
|
Pink: "Rózsaszín",
|
||||||
|
"Search...": "Keres...",
|
||||||
|
"Avg. Ping": "Átl. ping",
|
||||||
|
"Avg. Response": "Átl. válasz",
|
||||||
|
"Entry Page": "Nyitólap",
|
||||||
|
statusPageNothing: "Semmi nincs itt, kérem, adjon hozzá egy figyelőt.",
|
||||||
|
"No Services": "Nincs szolgáltatás",
|
||||||
|
"All Systems Operational": "Minden rendszer működik",
|
||||||
|
"Partially Degraded Service": "Részlegesen leállt szolgáltatás",
|
||||||
|
"Degraded Service": "Leállt szolgáltatás",
|
||||||
|
"Add Group": "Csoport hozzáadása",
|
||||||
|
"Add a monitor": "Figyelő hozzáadása",
|
||||||
|
"Edit Status Page": "Sátusz oldal szerkesztése",
|
||||||
|
"Go to Dashboard": "Menj az irányítópulthoz",
|
||||||
|
telegram: "Telegram",
|
||||||
|
webhook: "Webhook",
|
||||||
|
smtp: "Email (SMTP)",
|
||||||
|
discord: "Discord",
|
||||||
|
teams: "Microsoft Teams",
|
||||||
|
signal: "Signal",
|
||||||
|
gotify: "Gotify",
|
||||||
|
slack: "Slack",
|
||||||
|
"rocket.chat": "Rocket.chat",
|
||||||
|
pushover: "Pushover",
|
||||||
|
pushy: "Pushy",
|
||||||
|
octopush: "Octopush",
|
||||||
|
lunasea: "LunaSea",
|
||||||
|
apprise: "Apprise (Support 50+ Notification services)",
|
||||||
|
pushbullet: "Pushbullet",
|
||||||
|
line: "Line Messenger",
|
||||||
|
mattermost: "Mattermost",
|
||||||
|
"Status Page": "Status Page",
|
||||||
|
};
|
@ -0,0 +1,9 @@
|
|||||||
|
const fs = require("fs");
|
||||||
|
|
||||||
|
const path = "./data/test-chrome-profile";
|
||||||
|
|
||||||
|
if (fs.existsSync(path)) {
|
||||||
|
fs.rmdirSync(path, {
|
||||||
|
recursive: true,
|
||||||
|
});
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
const fs = require("fs");
|
||||||
|
|
||||||
|
const path = "./data/test";
|
||||||
|
|
||||||
|
if (fs.existsSync(path)) {
|
||||||
|
fs.rmdirSync(path, {
|
||||||
|
recursive: true,
|
||||||
|
});
|
||||||
|
}
|
@ -0,0 +1,236 @@
|
|||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
const { Page, Browser } = require("puppeteer");
|
||||||
|
const { sleep } = require("../src/util");
|
||||||
|
const axios = require("axios");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set back the correct data type for page object
|
||||||
|
* @type {Page}
|
||||||
|
*/
|
||||||
|
page;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Browser}
|
||||||
|
*/
|
||||||
|
browser;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await page.setViewport({
|
||||||
|
width: 1280,
|
||||||
|
height: 720,
|
||||||
|
deviceScaleFactor: 1,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
const baseURL = "http://127.0.0.1:3002";
|
||||||
|
|
||||||
|
describe("Init", () => {
|
||||||
|
const title = "Uptime Kuma";
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await page.goto(baseURL);
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should be titled "${title}"`, async () => {
|
||||||
|
await expect(page.title()).resolves.toMatch(title);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Setup Page
|
||||||
|
it("Setup", async () => {
|
||||||
|
// Create an Admin
|
||||||
|
await page.waitForSelector("#floatingInput");
|
||||||
|
await page.waitForSelector("#repeat");
|
||||||
|
await page.click("#floatingInput");
|
||||||
|
await page.type("#floatingInput", "admin");
|
||||||
|
await page.type("#floatingPassword", "admin123");
|
||||||
|
await page.type("#repeat", "admin123");
|
||||||
|
await page.click(".btn-primary[type=submit]");
|
||||||
|
await sleep(3000);
|
||||||
|
|
||||||
|
// Go to /setup again
|
||||||
|
await page.goto(baseURL + "/setup");
|
||||||
|
await sleep(3000);
|
||||||
|
let pathname = await page.evaluate(() => location.pathname);
|
||||||
|
expect(pathname).toEqual("/dashboard");
|
||||||
|
|
||||||
|
// Go to /
|
||||||
|
await page.goto(baseURL);
|
||||||
|
await sleep(3000);
|
||||||
|
pathname = await page.evaluate(() => location.pathname);
|
||||||
|
expect(pathname).toEqual("/dashboard");
|
||||||
|
});
|
||||||
|
|
||||||
|
// Settings Page
|
||||||
|
describe("Settings", () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
await page.goto(baseURL + "/settings");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Change Language", async () => {
|
||||||
|
await page.waitForSelector("#language");
|
||||||
|
|
||||||
|
await page.select("#language", "zh-HK");
|
||||||
|
let languageTitle = await page.evaluate(() => document.querySelector("[for=language]").innerText);
|
||||||
|
expect(languageTitle).toMatch("語言");
|
||||||
|
|
||||||
|
await page.select("#language", "en");
|
||||||
|
languageTitle = await page.evaluate(() => document.querySelector("[for=language]").innerText);
|
||||||
|
expect(languageTitle).toMatch("Language");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Change Theme", async () => {
|
||||||
|
await sleep(1000);
|
||||||
|
|
||||||
|
// Dark
|
||||||
|
await click(page, ".btn[for=btncheck2]");
|
||||||
|
await page.waitForSelector("div.dark");
|
||||||
|
|
||||||
|
await sleep(1000);
|
||||||
|
|
||||||
|
// Light
|
||||||
|
await click(page, ".btn[for=btncheck1]");
|
||||||
|
await page.waitForSelector("div.light");
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: Heartbeat Bar Style
|
||||||
|
|
||||||
|
// TODO: Timezone
|
||||||
|
|
||||||
|
it("Search Engine Visibility", async () => {
|
||||||
|
// Default
|
||||||
|
let res = await axios.get(baseURL + "/robots.txt");
|
||||||
|
expect(res.data).toMatch("Disallow: /");
|
||||||
|
|
||||||
|
// Yes
|
||||||
|
await click(page, "#searchEngineIndexYes");
|
||||||
|
await click(page, "form > div > .btn[type=submit]");
|
||||||
|
await sleep(2000);
|
||||||
|
res = await axios.get(baseURL + "/robots.txt");
|
||||||
|
expect(res.data).not.toMatch("Disallow: /");
|
||||||
|
|
||||||
|
// No
|
||||||
|
await click(page, "#searchEngineIndexNo");
|
||||||
|
await click(page, "form > div > .btn[type=submit]");
|
||||||
|
await sleep(2000);
|
||||||
|
res = await axios.get(baseURL + "/robots.txt");
|
||||||
|
expect(res.data).toMatch("Disallow: /");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Entry Page", async () => {
|
||||||
|
const newPage = await browser.newPage();
|
||||||
|
|
||||||
|
// Default
|
||||||
|
await newPage.goto(baseURL);
|
||||||
|
await sleep(3000);
|
||||||
|
let pathname = await newPage.evaluate(() => location.pathname);
|
||||||
|
expect(pathname).toEqual("/dashboard");
|
||||||
|
|
||||||
|
// Status Page
|
||||||
|
await click(page, "#entryPageNo");
|
||||||
|
await click(page, "form > div > .btn[type=submit]");
|
||||||
|
await sleep(2000);
|
||||||
|
await newPage.goto(baseURL);
|
||||||
|
await sleep(3000);
|
||||||
|
pathname = await newPage.evaluate(() => location.pathname);
|
||||||
|
expect(pathname).toEqual("/status");
|
||||||
|
|
||||||
|
// Back to Dashboard
|
||||||
|
await click(page, "#entryPageYes");
|
||||||
|
await click(page, "form > div > .btn[type=submit]");
|
||||||
|
await sleep(2000);
|
||||||
|
await newPage.goto(baseURL);
|
||||||
|
await sleep(3000);
|
||||||
|
pathname = await newPage.evaluate(() => location.pathname);
|
||||||
|
expect(pathname).toEqual("/dashboard");
|
||||||
|
|
||||||
|
await newPage.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Change Password (wrong current password)", async () => {
|
||||||
|
await page.type("#current-password", "wrong_passw$$d");
|
||||||
|
await page.type("#new-password", "new_password123");
|
||||||
|
await page.type("#repeat-new-password", "new_password123");
|
||||||
|
await click(page, "form > div > .btn[type=submit]", 1);
|
||||||
|
await sleep(3000);
|
||||||
|
await click(page, ".btn-danger.btn.me-1");
|
||||||
|
await sleep(2000);
|
||||||
|
await login("admin", "new_password123");
|
||||||
|
await sleep(2000);
|
||||||
|
let elementCount = await page.evaluate(() => document.querySelectorAll("#floatingPassword").length);
|
||||||
|
expect(elementCount).toEqual(1);
|
||||||
|
|
||||||
|
await login("admin", "admin123");
|
||||||
|
await sleep(3000);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Change Password (wrong repeat)", async () => {
|
||||||
|
await page.type("#current-password", "admin123");
|
||||||
|
await page.type("#new-password", "new_password123");
|
||||||
|
await page.type("#repeat-new-password", "new_password1234567898797898");
|
||||||
|
await click(page, "form > div > .btn[type=submit]", 1);
|
||||||
|
await sleep(3000);
|
||||||
|
await click(page, ".btn-danger.btn.me-1");
|
||||||
|
await sleep(2000);
|
||||||
|
await login("admin", "new_password123");
|
||||||
|
await sleep(2000);
|
||||||
|
let elementCount = await page.evaluate(() => document.querySelectorAll("#floatingPassword").length);
|
||||||
|
expect(elementCount).toEqual(1);
|
||||||
|
|
||||||
|
await login("admin", "admin123");
|
||||||
|
await sleep(3000);
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: 2FA
|
||||||
|
|
||||||
|
// TODO: Export Backup
|
||||||
|
|
||||||
|
// TODO: Import Backup
|
||||||
|
|
||||||
|
// TODO: Disable Auth
|
||||||
|
|
||||||
|
// TODO: Clear Stats
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO
|
||||||
|
* Create Monitor - All type
|
||||||
|
* Edit Monitor
|
||||||
|
* Delete Monitor
|
||||||
|
*
|
||||||
|
* Create Notification (token problem, maybe hard to test)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
describe("Status Page", () => {
|
||||||
|
const title = "Uptime Kuma";
|
||||||
|
beforeAll(async () => {
|
||||||
|
await page.goto(baseURL + "/status");
|
||||||
|
});
|
||||||
|
it(`should be titled "${title}"`, async () => {
|
||||||
|
await expect(page.title()).resolves.toMatch(title);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
async function login(username, password) {
|
||||||
|
await input(page, "#floatingInput", username);
|
||||||
|
await input(page, "#floatingPassword", password);
|
||||||
|
await page.click(".btn-primary[type=submit]");
|
||||||
|
}
|
||||||
|
|
||||||
|
async function click(page, selector, elementIndex = 0) {
|
||||||
|
return await page.evaluate((s, i) => {
|
||||||
|
return document.querySelectorAll(s)[i].click();
|
||||||
|
}, selector, elementIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function input(page, selector, text) {
|
||||||
|
const element = await page.$(selector);
|
||||||
|
await element.click({ clickCount: 3 });
|
||||||
|
await page.keyboard.press("Backspace");
|
||||||
|
await page.type(selector, text);
|
||||||
|
}
|
Loading…
Reference in new issue