Test: Fix tests

Test: Add clear stats test

Test: Attempt to fix tests

Test: Add test for disable auth

Update README
pull/753/head
Nelson Chan 2021-11-04 23:19:31 +08:00
parent f65cc655c0
commit 07742799ed
9 changed files with 101 additions and 35 deletions

View File

@ -2,5 +2,11 @@ module.exports = {
"launch": {
"headless": process.env.HEADLESS_TEST || false,
"userDataDir": "./data/test-chrome-profile",
args: [
"--no-sandbox",
"--disable-setuid-sandbox",
"--disable-gpu",
"--disable-dev-shm-usage"
],
}
};

View File

@ -22,7 +22,7 @@
"build": "vite build --config ./config/vite.config.js",
"test": "node test/prepare-test-server.js && node server/server.js --port=3002 --data-dir=./data/test/ --test",
"test-with-build": "npm run build && npm test",
"jest": "node test/prepare-jest.js && npm run jest-frontend && npm run jest-backend && jest --config=./config/jest.config.js",
"jest": "node test/prepare-jest.js && npm run jest-frontend && npm run jest-backend && jest --runInBand --config=./config/jest.config.js",
"jest-frontend": "cross-env TEST_FRONTEND=1 jest --config=./config/jest-frontend.config.js",
"jest-backend": "cross-env TEST_BACKEND=1 jest --config=./config/jest-backend.config.js",
"tsc": "tsc",

View File

@ -79,7 +79,7 @@ class Database {
console.log(`Data Dir: ${Database.dataDir}`);
}
static async connect() {
static async connect(testMode = false) {
const acquireConnectionTimeout = 120 * 1000;
const Dialect = require("knex/lib/dialects/sqlite3/index.js");
@ -112,8 +112,13 @@ class Database {
await R.autoloadModels("./server/model");
await R.exec("PRAGMA foreign_keys = ON");
// Change to WAL
await R.exec("PRAGMA journal_mode = WAL");
if (testMode) {
// Change to MEMORY
await R.exec("PRAGMA journal_mode = MEMORY");
} else {
// Change to WAL
await R.exec("PRAGMA journal_mode = WAL");
}
await R.exec("PRAGMA cache_size = -12000");
await R.exec("PRAGMA auto_vacuum = FULL");

View File

@ -176,7 +176,7 @@ exports.entryPage = "dashboard";
(async () => {
Database.init(args);
await initDatabase();
await initDatabase(testMode);
exports.entryPage = await setting("entryPage");
@ -1417,14 +1417,14 @@ async function getMonitorJSONList(userID) {
return result;
}
async function initDatabase() {
async function initDatabase(testMode = false) {
if (! fs.existsSync(Database.path)) {
console.log("Copying Database");
fs.copyFileSync(Database.templatePath, Database.path);
}
console.log("Connecting to the Database");
await Database.connect();
await Database.connect(testMode);
console.log("Connected");
// Patch the database

View File

@ -26,6 +26,7 @@
<div class="form-text mt-2 mb-4 ms-2">{{ $t("shrinkDatabaseDescription") }}</div>
</div>
<button
id="clearAllStats-btn"
class="btn btn-outline-danger me-2 mb-2"
@click="confirmClearStatistics"
>

View File

@ -5,7 +5,7 @@
<template v-if="!settings.disableAuth">
<p>
{{ $t("Current User") }}: <strong>{{ username }}</strong>
<button v-if="! settings.disableAuth" class="btn btn-danger ms-4 me-2 mb-2" @click="$root.logout">{{ $t("Logout") }}</button>
<button v-if="! settings.disableAuth" id="logout-btn" class="btn btn-danger ms-4 me-2 mb-2" @click="$root.logout">{{ $t("Logout") }}</button>
</p>
<h5 class="my-4">{{ $t("Change Password") }}</h5>
@ -81,8 +81,8 @@
<h5 class="my-4">{{ $t("Advanced") }}</h5>
<div class="mb-4">
<button v-if="settings.disableAuth" class="btn btn-outline-primary me-2 mb-2" @click="enableAuth">{{ $t("Enable Auth") }}</button>
<button v-if="! settings.disableAuth" class="btn btn-primary me-2 mb-2" @click="confirmDisableAuth">{{ $t("Disable Auth") }}</button>
<button v-if="settings.disableAuth" id="enableAuth-btn" class="btn btn-outline-primary me-2 mb-2" @click="enableAuth">{{ $t("Enable Auth") }}</button>
<button v-if="! settings.disableAuth" id="disableAuth-btn" class="btn btn-primary me-2 mb-2" @click="confirmDisableAuth">{{ $t("Disable Auth") }}</button>
</div>
</div>
</div>

View File

@ -4,7 +4,7 @@
2. Create a language file (e.g. `zh-TW.js`). The filename must be ISO language code: http://www.lingoes.net/en/translator/langcode.htm
3. Run `npm run update-language-files`. You can also use this command to check if there are new strings to translate for your language.
4. Your language file should be filled in. You can translate now.
5. Translate `src/pages/Settings.vue` (search for a `Confirm` component with `rel="confirmDisableAuth"`).
5. Translate `src/components/settings/Security.vue` (search for a `Confirm` component with `rel="confirmDisableAuth"`).
6. Import your language file in `src/i18n.js` and add it to `languageList` constant.
7. Make a [pull request](https://github.com/louislam/uptime-kuma/pulls) when you have done.

View File

@ -194,7 +194,7 @@
</div>
<div class="mt-5 mb-1">
<button class="btn btn-primary" type="submit" :disabled="processing">{{ $t("Save") }}</button>
<button id="monitor-submit-btn" class="btn btn-primary" type="submit" :disabled="processing">{{ $t("Save") }}</button>
</div>
</div>

View File

@ -59,18 +59,31 @@ describe("Init", () => {
// Go to /
await page.goto(baseURL);
await sleep(3000);
await page.waitForSelector("h1.mb-3");
pathname = await page.evaluate(() => location.pathname);
expect(pathname).toEqual("/dashboard");
});
it("should create monitor", async () => {
// Create monitor
await page.goto(baseURL + "/add");
await page.waitForSelector("#name");
await page.type("#name", "Myself");
await page.waitForSelector("#url");
await page.click("#url", { clickCount: 3 });
await page.keyboard.type(baseURL);
await page.keyboard.press("Enter");
});
// Settings Page
describe("Settings", () => {
beforeAll(async () => {
beforeEach(async () => {
await page.goto(baseURL + "/settings");
});
it("Change Language", async () => {
await page.goto(baseURL + "/settings/appearance");
await page.waitForSelector("#language");
await page.select("#language", "zh-HK");
@ -83,20 +96,33 @@ describe("Init", () => {
});
it("Change Theme", async () => {
await sleep(1000);
await page.goto(baseURL + "/settings/appearance");
// Dark
await click(page, ".btn[for=btncheck2]");
await page.waitForSelector("div.dark");
await sleep(1000);
await page.waitForSelector(".btn[for=btncheck1]");
// Light
await click(page, ".btn[for=btncheck1]");
await page.waitForSelector("div.light");
});
// TODO: Heartbeat Bar Style
it("Change Heartbeat Bar Style", async () => {
await page.goto(baseURL + "/settings/appearance");
// Bottom
await click(page, ".btn[for=btncheck5]");
await page.waitForSelector("div.hp-bar-big");
// None
await click(page, ".btn[for=btncheck6]");
await page.waitForSelector("div.hp-bar-big", {
hidden: true,
timeout: 1000
});
});
// TODO: Timezone
@ -108,14 +134,14 @@ describe("Init", () => {
// Yes
await click(page, "#searchEngineIndexYes");
await click(page, "form > div > .btn[type=submit]");
await sleep(2000);
await sleep(1000);
res = await axios.get(baseURL + "/robots.txt");
expect(res.data).not.toContain("Disallow: /");
// No
await click(page, "#searchEngineIndexNo");
await click(page, "form > div > .btn[type=submit]");
await sleep(2000);
await sleep(1000);
res = await axios.get(baseURL + "/robots.txt");
expect(res.data).toContain("Disallow: /");
});
@ -125,25 +151,25 @@ describe("Init", () => {
// Default
await newPage.goto(baseURL);
await sleep(3000);
await newPage.waitForSelector("h1.mb-3", { timeout: 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(4000);
await sleep(1000);
await newPage.goto(baseURL);
await sleep(4000);
await newPage.waitForSelector("img.logo", { timeout: 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(4000);
await sleep(1000);
await newPage.goto(baseURL);
await sleep(4000);
await newPage.waitForSelector("h1.mb-3", { timeout: 3000 });
pathname = await newPage.evaluate(() => location.pathname);
expect(pathname).toEqual("/dashboard");
@ -151,7 +177,7 @@ describe("Init", () => {
});
it("Change Password (wrong current password)", async () => {
await page.goto(baseURL + "/settings");
await page.goto(baseURL + "/settings/security");
await page.waitForSelector("#current-password");
await page.type("#current-password", "wrong_passw$$d");
@ -159,10 +185,10 @@ describe("Init", () => {
await page.type("#repeat-new-password", "new_password123");
// Save
await click(page, "form > div > .btn[type=submit]", 1);
await sleep(4000);
await click(page, "form > div > .btn[type=submit]", 0);
await sleep(1000);
await click(page, ".btn-danger.btn.me-2");
await click(page, "#logout-btn");
await login("admin", "new_password123");
let elementCount = await page.evaluate(() => document.querySelectorAll("#floatingPassword").length);
expect(elementCount).toEqual(1);
@ -171,24 +197,26 @@ describe("Init", () => {
});
it("Change Password (wrong repeat)", async () => {
await page.goto(baseURL + "/settings");
await page.goto(baseURL + "/settings/security");
await page.waitForSelector("#current-password");
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(4000);
await click(page, "form > div > .btn[type=submit]", 0);
await sleep(1000);
await click(page, ".btn-danger.btn.me-2");
await click(page, "#logout-btn");
await login("admin", "new_password123");
let elementCount = await page.evaluate(() => document.querySelectorAll("#floatingPassword").length);
expect(elementCount).toEqual(1);
await login("admin", "admin123");
await sleep(3000);
await page.waitForSelector("#current-password");
let pathname = await page.evaluate(() => location.pathname);
expect(pathname).toEqual("/settings/security");
});
// TODO: 2FA
@ -197,9 +225,35 @@ describe("Init", () => {
// TODO: Import Backup
// TODO: Disable Auth
it("Should disable & enable auth", async () => {
await page.goto(baseURL + "/settings/security");
await click(page, "#disableAuth-btn");
await click(page, ".btn.btn-danger[data-bs-dismiss='modal']", 2); // Not a good way to do it
await page.waitForSelector("#enableAuth-btn", { timeout: 3000 });
await page.waitForSelector("#logout-btn", {
hidden: true,
timeout: 3000
});
// TODO: Clear Stats
const newPage = await browser.newPage();
await newPage.goto(baseURL);
await newPage.waitForSelector("span.badge", { timeout: 3000 });
newPage.close();
await click(page, "#enableAuth-btn");
await login("admin", "admin123");
await page.waitForSelector("#disableAuth-btn", { timeout: 3000 });
});
it("Should clear all statistics", async () => {
await page.goto(baseURL + "/settings/monitor-history");
await click(page, "#clearAllStats-btn");
await click(page, ".btn.btn-danger");
await page.waitForFunction(() => {
const badge = document.querySelector("span.badge");
return badge && badge.innerText == "0%";
}, { timeout: 3000 });
});
});
/*