Playwright + Native Node Test Runner (#3893)
parent
f24c3583fb
commit
996ff28ed9
@ -0,0 +1,60 @@
|
|||||||
|
import { defineConfig, devices } from "@playwright/test";
|
||||||
|
|
||||||
|
const port = 30001;
|
||||||
|
const url = `http://localhost:${port}`;
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
// Look for test files in the "tests" directory, relative to this configuration file.
|
||||||
|
testDir: "../test/e2e",
|
||||||
|
outputDir: "../private/playwright-test-results",
|
||||||
|
fullyParallel: false,
|
||||||
|
locale: "en-US",
|
||||||
|
|
||||||
|
// Fail the build on CI if you accidentally left test.only in the source code.
|
||||||
|
forbidOnly: !!process.env.CI,
|
||||||
|
|
||||||
|
// Retry on CI only.
|
||||||
|
retries: process.env.CI ? 2 : 0,
|
||||||
|
|
||||||
|
// Opt out of parallel tests on CI.
|
||||||
|
workers: 1,
|
||||||
|
|
||||||
|
// Reporter to use
|
||||||
|
reporter: [
|
||||||
|
[
|
||||||
|
"html", {
|
||||||
|
outputFolder: "../private/playwright-report",
|
||||||
|
open: "never",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
],
|
||||||
|
|
||||||
|
use: {
|
||||||
|
// Base URL to use in actions like `await page.goto('/')`.
|
||||||
|
baseURL: url,
|
||||||
|
|
||||||
|
// Collect trace when retrying the failed test.
|
||||||
|
trace: "on-first-retry",
|
||||||
|
},
|
||||||
|
|
||||||
|
// Configure projects for major browsers.
|
||||||
|
projects: [
|
||||||
|
{
|
||||||
|
name: "chromium",
|
||||||
|
use: { ...devices["Desktop Chrome"] },
|
||||||
|
},
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
name: "firefox",
|
||||||
|
use: { browserName: "firefox" }
|
||||||
|
},*/
|
||||||
|
],
|
||||||
|
|
||||||
|
// Run your local dev server before starting the tests.
|
||||||
|
webServer: {
|
||||||
|
command: `node extra/remove-playwright-test-data.js && node server/server.js --port=${port} --data-dir=./data/playwright-test`,
|
||||||
|
url,
|
||||||
|
reuseExistingServer: false,
|
||||||
|
cwd: "../",
|
||||||
|
},
|
||||||
|
});
|
@ -0,0 +1,6 @@
|
|||||||
|
const fs = require("fs");
|
||||||
|
|
||||||
|
fs.rmSync("./data/playwright-test", {
|
||||||
|
recursive: true,
|
||||||
|
force: true,
|
||||||
|
});
|
File diff suppressed because it is too large
Load Diff
@ -1,323 +0,0 @@
|
|||||||
// ⚠️⚠️⚠️ Deprecated: Jest is not recommended for testing backend code anymore, please create a new test file in ./test/backend-test which are native Node.js test files.
|
|
||||||
|
|
||||||
const { genSecret, DOWN, log} = require("../src/util");
|
|
||||||
const utilServer = require("../server/util-server");
|
|
||||||
const Discord = require("../server/notification-providers/discord");
|
|
||||||
const axios = require("axios");
|
|
||||||
const { UptimeKumaServer } = require("../server/uptime-kuma-server");
|
|
||||||
const Database = require("../server/database");
|
|
||||||
const {Settings} = require("../server/settings");
|
|
||||||
const fs = require("fs");
|
|
||||||
const dayjs = require("dayjs");
|
|
||||||
dayjs.extend(require("dayjs/plugin/utc"));
|
|
||||||
dayjs.extend(require("dayjs/plugin/timezone"));
|
|
||||||
|
|
||||||
jest.mock("axios");
|
|
||||||
|
|
||||||
describe("Test parseCertificateInfo", () => {
|
|
||||||
it("should handle undefined", async () => {
|
|
||||||
const parseCertificateInfo = utilServer.__getPrivateFunction("parseCertificateInfo");
|
|
||||||
const info = parseCertificateInfo(undefined);
|
|
||||||
expect(info).toEqual(undefined);
|
|
||||||
}, 5000);
|
|
||||||
|
|
||||||
it("should handle normal cert chain", async () => {
|
|
||||||
const parseCertificateInfo = utilServer.__getPrivateFunction("parseCertificateInfo");
|
|
||||||
|
|
||||||
const chain1 = {
|
|
||||||
fingerprint: "CF:2C:F3:6A:FE:6B:10:EC:44:77:C8:95:BB:96:2E:06:1F:0E:15:DA",
|
|
||||||
valid_from: "Oct 22 12:00:00 2013 GMT",
|
|
||||||
valid_to: "Oct 22 12:00:00 2028 GMT",
|
|
||||||
subjectaltname: "DNS:www.example.org, DNS:example.com, DNS:example.edu, DNS:example.net, DNS:example.org, DNS:www.example.com, DNS:www.example.edu, DNS:www.example.net",
|
|
||||||
};
|
|
||||||
|
|
||||||
const chain2 = {
|
|
||||||
fingerprint: "A0:31:C4:67:82:E6:E6:C6:62:C2:C8:7C:76:DA:9A:A6:2C:CA:BD:8E",
|
|
||||||
valid_from: "Oct 22 12:00:00 2013 GMT",
|
|
||||||
valid_to: "Oct 22 12:00:00 2028 GMT",
|
|
||||||
subjectaltname: "DNS:www.example.org, DNS:example.com, DNS:example.edu, DNS:example.net, DNS:example.org, DNS:www.example.com, DNS:www.example.edu, DNS:www.example.net",
|
|
||||||
};
|
|
||||||
|
|
||||||
const chain3 = {
|
|
||||||
fingerprint: "5F:B7:EE:06:33:E2:59:DB:AD:0C:4C:9A:E6:D3:8F:1A:61:C7:DC:25",
|
|
||||||
valid_from: "Oct 22 12:00:00 2013 GMT",
|
|
||||||
valid_to: "Oct 22 12:00:00 2028 GMT",
|
|
||||||
subjectaltname: "DNS:www.example.org, DNS:example.com, DNS:example.edu, DNS:example.net, DNS:example.org, DNS:www.example.com, DNS:www.example.edu, DNS:www.example.net",
|
|
||||||
};
|
|
||||||
|
|
||||||
chain1.issuerCertificate = chain2;
|
|
||||||
chain2.issuerCertificate = chain3;
|
|
||||||
chain3.issuerCertificate = chain3;
|
|
||||||
|
|
||||||
const info = parseCertificateInfo(chain1);
|
|
||||||
expect(chain1).toEqual(info);
|
|
||||||
}, 5000);
|
|
||||||
|
|
||||||
it("should handle cert chain with strange circle", async () => {
|
|
||||||
const parseCertificateInfo = utilServer.__getPrivateFunction("parseCertificateInfo");
|
|
||||||
|
|
||||||
const chain1 = {
|
|
||||||
fingerprint: "CF:2C:F3:6A:FE:6B:10:EC:44:77:C8:95:BB:96:2E:06:1F:0E:15:DA",
|
|
||||||
valid_from: "Oct 22 12:00:00 2013 GMT",
|
|
||||||
valid_to: "Oct 22 12:00:00 2028 GMT",
|
|
||||||
subjectaltname: "DNS:www.example.org, DNS:example.com, DNS:example.edu, DNS:example.net, DNS:example.org, DNS:www.example.com, DNS:www.example.edu, DNS:www.example.net",
|
|
||||||
};
|
|
||||||
|
|
||||||
const chain2 = {
|
|
||||||
fingerprint: "A0:31:C4:67:82:E6:E6:C6:62:C2:C8:7C:76:DA:9A:A6:2C:CA:BD:8E",
|
|
||||||
valid_from: "Oct 22 12:00:00 2013 GMT",
|
|
||||||
valid_to: "Oct 22 12:00:00 2028 GMT",
|
|
||||||
subjectaltname: "DNS:www.example.org, DNS:example.com, DNS:example.edu, DNS:example.net, DNS:example.org, DNS:www.example.com, DNS:www.example.edu, DNS:www.example.net",
|
|
||||||
};
|
|
||||||
|
|
||||||
const chain3 = {
|
|
||||||
fingerprint: "5F:B7:EE:06:33:E2:59:DB:AD:0C:4C:9A:E6:D3:8F:1A:61:C7:DC:25",
|
|
||||||
valid_from: "Oct 22 12:00:00 2013 GMT",
|
|
||||||
valid_to: "Oct 22 12:00:00 2028 GMT",
|
|
||||||
subjectaltname: "DNS:www.example.org, DNS:example.com, DNS:example.edu, DNS:example.net, DNS:example.org, DNS:www.example.com, DNS:www.example.edu, DNS:www.example.net",
|
|
||||||
};
|
|
||||||
|
|
||||||
const chain4 = {
|
|
||||||
fingerprint: "haha",
|
|
||||||
valid_from: "Oct 22 12:00:00 2013 GMT",
|
|
||||||
valid_to: "Oct 22 12:00:00 2028 GMT",
|
|
||||||
subjectaltname: "DNS:www.example.org, DNS:example.com, DNS:example.edu, DNS:example.net, DNS:example.org, DNS:www.example.com, DNS:www.example.edu, DNS:www.example.net",
|
|
||||||
};
|
|
||||||
|
|
||||||
chain1.issuerCertificate = chain2;
|
|
||||||
chain2.issuerCertificate = chain3;
|
|
||||||
chain3.issuerCertificate = chain4;
|
|
||||||
chain4.issuerCertificate = chain2;
|
|
||||||
|
|
||||||
const info = parseCertificateInfo(chain1);
|
|
||||||
expect(chain1).toEqual(info);
|
|
||||||
}, 5000);
|
|
||||||
|
|
||||||
it("should handle cert chain with last undefined (should be happen in real, but just in case)", async () => {
|
|
||||||
const parseCertificateInfo = utilServer.__getPrivateFunction("parseCertificateInfo");
|
|
||||||
|
|
||||||
const chain1 = {
|
|
||||||
fingerprint: "CF:2C:F3:6A:FE:6B:10:EC:44:77:C8:95:BB:96:2E:06:1F:0E:15:DA",
|
|
||||||
valid_from: "Oct 22 12:00:00 2013 GMT",
|
|
||||||
valid_to: "Oct 22 12:00:00 2028 GMT",
|
|
||||||
subjectaltname: "DNS:www.example.org, DNS:example.com, DNS:example.edu, DNS:example.net, DNS:example.org, DNS:www.example.com, DNS:www.example.edu, DNS:www.example.net",
|
|
||||||
};
|
|
||||||
|
|
||||||
const chain2 = {
|
|
||||||
fingerprint: "A0:31:C4:67:82:E6:E6:C6:62:C2:C8:7C:76:DA:9A:A6:2C:CA:BD:8E",
|
|
||||||
valid_from: "Oct 22 12:00:00 2013 GMT",
|
|
||||||
valid_to: "Oct 22 12:00:00 2028 GMT",
|
|
||||||
subjectaltname: "DNS:www.example.org, DNS:example.com, DNS:example.edu, DNS:example.net, DNS:example.org, DNS:www.example.com, DNS:www.example.edu, DNS:www.example.net",
|
|
||||||
};
|
|
||||||
|
|
||||||
const chain3 = {
|
|
||||||
fingerprint: "5F:B7:EE:06:33:E2:59:DB:AD:0C:4C:9A:E6:D3:8F:1A:61:C7:DC:25",
|
|
||||||
valid_from: "Oct 22 12:00:00 2013 GMT",
|
|
||||||
valid_to: "Oct 22 12:00:00 2028 GMT",
|
|
||||||
subjectaltname: "DNS:www.example.org, DNS:example.com, DNS:example.edu, DNS:example.net, DNS:example.org, DNS:www.example.com, DNS:www.example.edu, DNS:www.example.net",
|
|
||||||
};
|
|
||||||
|
|
||||||
const chain4 = {
|
|
||||||
fingerprint: "haha",
|
|
||||||
valid_from: "Oct 22 12:00:00 2013 GMT",
|
|
||||||
valid_to: "Oct 22 12:00:00 2028 GMT",
|
|
||||||
subjectaltname: "DNS:www.example.org, DNS:example.com, DNS:example.edu, DNS:example.net, DNS:example.org, DNS:www.example.com, DNS:www.example.edu, DNS:www.example.net",
|
|
||||||
};
|
|
||||||
|
|
||||||
chain1.issuerCertificate = chain2;
|
|
||||||
chain2.issuerCertificate = chain3;
|
|
||||||
chain3.issuerCertificate = chain4;
|
|
||||||
chain4.issuerCertificate = undefined;
|
|
||||||
|
|
||||||
const info = parseCertificateInfo(chain1);
|
|
||||||
expect(chain1).toEqual(info);
|
|
||||||
}, 5000);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("Test genSecret", () => {
|
|
||||||
|
|
||||||
beforeAll(() => {
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should be correct length", () => {
|
|
||||||
let secret = genSecret(-1);
|
|
||||||
expect(secret).toEqual("");
|
|
||||||
|
|
||||||
secret = genSecret(0);
|
|
||||||
expect(secret).toEqual("");
|
|
||||||
|
|
||||||
secret = genSecret(1);
|
|
||||||
expect(secret.length).toEqual(1);
|
|
||||||
|
|
||||||
secret = genSecret(2);
|
|
||||||
expect(secret.length).toEqual(2);
|
|
||||||
|
|
||||||
secret = genSecret(64);
|
|
||||||
expect(secret.length).toEqual(64);
|
|
||||||
|
|
||||||
secret = genSecret(9000);
|
|
||||||
expect(secret.length).toEqual(9000);
|
|
||||||
|
|
||||||
secret = genSecret(90000);
|
|
||||||
expect(secret.length).toEqual(90000);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should contain first and last possible chars", () => {
|
|
||||||
let secret = genSecret(90000);
|
|
||||||
expect(secret).toContain("A");
|
|
||||||
expect(secret).toContain("9");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("Test reset-password", () => {
|
|
||||||
it("should able to run", async () => {
|
|
||||||
await require("../extra/reset-password").main();
|
|
||||||
}, 120000);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("Test Discord Notification Provider", () => {
|
|
||||||
const hostname = "discord.com";
|
|
||||||
const port = 1337;
|
|
||||||
|
|
||||||
const sendNotification = async (hostname, port, type) => {
|
|
||||||
const discordProvider = new Discord();
|
|
||||||
|
|
||||||
axios.post.mockResolvedValue({});
|
|
||||||
|
|
||||||
await discordProvider.send(
|
|
||||||
{
|
|
||||||
discordUsername: "Uptime Kuma",
|
|
||||||
discordWebhookUrl: "https://discord.com",
|
|
||||||
},
|
|
||||||
"test message",
|
|
||||||
{
|
|
||||||
type,
|
|
||||||
hostname,
|
|
||||||
port,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
status: DOWN,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
it("should send hostname for ping monitors", async () => {
|
|
||||||
await sendNotification(hostname, null, "ping");
|
|
||||||
expect(axios.post.mock.lastCall[1].embeds[0].fields[1].value).toBe(hostname);
|
|
||||||
});
|
|
||||||
|
|
||||||
it.each([ "dns", "port", "steam" ])("should send hostname for %p monitors", async (type) => {
|
|
||||||
await sendNotification(hostname, port, type);
|
|
||||||
expect(axios.post.mock.lastCall[1].embeds[0].fields[1].value).toBe(`${hostname}:${port}`);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("The function filterAndJoin", () => {
|
|
||||||
it("should join and array of strings to one string", () => {
|
|
||||||
const result = utilServer.filterAndJoin([ "one", "two", "three" ]);
|
|
||||||
expect(result).toBe("onetwothree");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should join strings using a given connector", () => {
|
|
||||||
const result = utilServer.filterAndJoin([ "one", "two", "three" ], "-");
|
|
||||||
expect(result).toBe("one-two-three");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should filter null, undefined and empty strings before joining", () => {
|
|
||||||
const result = utilServer.filterAndJoin([ undefined, "", "three" ], "--");
|
|
||||||
expect(result).toBe("three");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return an empty string if all parts are filtered out", () => {
|
|
||||||
const result = utilServer.filterAndJoin([ undefined, "", "" ], "--");
|
|
||||||
expect(result).toBe("");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("Test uptimeKumaServer.getClientIP()", () => {
|
|
||||||
it("should able to get a correct client IP", async () => {
|
|
||||||
Database.initDataDir({
|
|
||||||
"data-dir": "./data/test"
|
|
||||||
});
|
|
||||||
|
|
||||||
if (! fs.existsSync(Database.sqlitePath)) {
|
|
||||||
log.info("server", "Copying Database");
|
|
||||||
fs.copyFileSync(Database.templatePath, Database.sqlitePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
await Database.connect(true);
|
|
||||||
await Database.patch();
|
|
||||||
|
|
||||||
const fakeSocket = {
|
|
||||||
client: {
|
|
||||||
conn: {
|
|
||||||
remoteAddress: "192.168.10.10",
|
|
||||||
request: {
|
|
||||||
headers: {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const server = Object.create(UptimeKumaServer.prototype);
|
|
||||||
let ip = await server.getClientIP(fakeSocket);
|
|
||||||
|
|
||||||
await Settings.set("trustProxy", false);
|
|
||||||
expect(await Settings.get("trustProxy")).toBe(false);
|
|
||||||
expect(ip).toBe("192.168.10.10");
|
|
||||||
|
|
||||||
fakeSocket.client.conn.request.headers["x-forwarded-for"] = "10.10.10.10";
|
|
||||||
ip = await server.getClientIP(fakeSocket);
|
|
||||||
expect(ip).toBe("192.168.10.10");
|
|
||||||
|
|
||||||
fakeSocket.client.conn.request.headers["x-real-ip"] = "20.20.20.20";
|
|
||||||
ip = await server.getClientIP(fakeSocket);
|
|
||||||
expect(ip).toBe("192.168.10.10");
|
|
||||||
|
|
||||||
await Settings.set("trustProxy", true);
|
|
||||||
expect(await Settings.get("trustProxy")).toBe(true);
|
|
||||||
|
|
||||||
fakeSocket.client.conn.request.headers["x-forwarded-for"] = "10.10.10.10";
|
|
||||||
ip = await server.getClientIP(fakeSocket);
|
|
||||||
expect(ip).toBe("10.10.10.10");
|
|
||||||
|
|
||||||
// x-real-ip
|
|
||||||
delete fakeSocket.client.conn.request.headers["x-forwarded-for"];
|
|
||||||
ip = await server.getClientIP(fakeSocket);
|
|
||||||
expect(ip).toBe("20.20.20.20");
|
|
||||||
|
|
||||||
fakeSocket.client.conn.request.headers["x-forwarded-for"] = "2001:db8:85a3:8d3:1319:8a2e:370:7348";
|
|
||||||
ip = await server.getClientIP(fakeSocket);
|
|
||||||
expect(ip).toBe("2001:db8:85a3:8d3:1319:8a2e:370:7348");
|
|
||||||
|
|
||||||
fakeSocket.client.conn.request.headers["x-forwarded-for"] = "203.0.113.195";
|
|
||||||
ip = await server.getClientIP(fakeSocket);
|
|
||||||
expect(ip).toBe("203.0.113.195");
|
|
||||||
|
|
||||||
fakeSocket.client.conn.request.headers["x-forwarded-for"] = "203.0.113.195, 2001:db8:85a3:8d3:1319:8a2e:370:7348";
|
|
||||||
ip = await server.getClientIP(fakeSocket);
|
|
||||||
expect(ip).toBe("203.0.113.195");
|
|
||||||
|
|
||||||
fakeSocket.client.conn.request.headers["x-forwarded-for"] = "203.0.113.195,2001:db8:85a3:8d3:1319:8a2e:370:7348,150.172.238.178";
|
|
||||||
ip = await server.getClientIP(fakeSocket);
|
|
||||||
expect(ip).toBe("203.0.113.195");
|
|
||||||
|
|
||||||
// Elements are comma-separated, with optional whitespace surrounding the commas.
|
|
||||||
fakeSocket.client.conn.request.headers["x-forwarded-for"] = "203.0.113.195 , 2001:db8:85a3:8d3:1319:8a2e:370:7348,150.172.238.178";
|
|
||||||
ip = await server.getClientIP(fakeSocket);
|
|
||||||
expect(ip).toBe("203.0.113.195");
|
|
||||||
|
|
||||||
fakeSocket.client.conn.remoteAddress = "2001:db8::1";
|
|
||||||
fakeSocket.client.conn.request.headers = {};
|
|
||||||
ip = await server.getClientIP(fakeSocket);
|
|
||||||
expect(ip).toBe("2001:db8::1");
|
|
||||||
|
|
||||||
fakeSocket.client.conn.remoteAddress = "::ffff:127.0.0.1";
|
|
||||||
fakeSocket.client.conn.request.headers = {};
|
|
||||||
ip = await server.getClientIP(fakeSocket);
|
|
||||||
expect(ip).toBe("127.0.0.1");
|
|
||||||
|
|
||||||
await Database.close();
|
|
||||||
}, 120000);
|
|
||||||
});
|
|
@ -1,18 +0,0 @@
|
|||||||
const actor = require("../support/actors/actor");
|
|
||||||
const userData = require("../support/const/user-data");
|
|
||||||
const dashboardPage = require("../support/pages/dashboard-page");
|
|
||||||
const setupPage = require("../support/pages/setup-page");
|
|
||||||
|
|
||||||
describe("user can create a new account on setup page", () => {
|
|
||||||
before(() => {
|
|
||||||
cy.visit("/setup");
|
|
||||||
});
|
|
||||||
it("user can create new account", () => {
|
|
||||||
cy.url().should("be.equal", setupPage.SetupPage.url);
|
|
||||||
actor.actor.setupTask.fillAndSubmitSetupForm(userData.DEFAULT_USER_DATA.username, userData.DEFAULT_USER_DATA.password, userData.DEFAULT_USER_DATA.password);
|
|
||||||
cy.url().should("be.equal", dashboardPage.DashboardPage.url);
|
|
||||||
cy.get('[role="alert"]')
|
|
||||||
.should("be.visible")
|
|
||||||
.and("contain.text", "Added Successfully.");
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,8 +0,0 @@
|
|||||||
const setupTask = require("../tasks/setup-task");
|
|
||||||
class Actor {
|
|
||||||
constructor() {
|
|
||||||
this.setupTask = new setupTask.SetupTask();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const actor = new Actor();
|
|
||||||
exports.actor = actor;
|
|
@ -1,4 +0,0 @@
|
|||||||
exports.DEFAULT_USER_DATA = {
|
|
||||||
username: "testuser",
|
|
||||||
password: "testuser123",
|
|
||||||
};
|
|
@ -1 +0,0 @@
|
|||||||
require("./commands");
|
|
@ -1,3 +0,0 @@
|
|||||||
exports.DashboardPage = {
|
|
||||||
url: Cypress.env("baseUrl") + "/dashboard",
|
|
||||||
};
|
|
@ -1,7 +0,0 @@
|
|||||||
exports.SetupPage = {
|
|
||||||
url: Cypress.env("baseUrl") + "/setup",
|
|
||||||
usernameInput: '[data-cy="username-input"]',
|
|
||||||
passWordInput: '[data-cy="password-input"]',
|
|
||||||
passwordRepeatInput: '[data-cy="password-repeat-input"]',
|
|
||||||
submitSetupForm: '[data-cy="submit-setup-form"]',
|
|
||||||
};
|
|
@ -1,11 +0,0 @@
|
|||||||
const setupPage = require("../pages/setup-page");
|
|
||||||
|
|
||||||
class SetupTask {
|
|
||||||
fillAndSubmitSetupForm(username, password, passwordRepeat) {
|
|
||||||
cy.get(setupPage.SetupPage.usernameInput).type(username);
|
|
||||||
cy.get(setupPage.SetupPage.passWordInput).type(password);
|
|
||||||
cy.get(setupPage.SetupPage.passwordRepeatInput).type(passwordRepeat);
|
|
||||||
cy.get(setupPage.SetupPage.submitSetupForm).click();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.SetupTask = SetupTask;
|
|
@ -1,44 +0,0 @@
|
|||||||
import { currentLocale } from "../../../src/i18n";
|
|
||||||
|
|
||||||
describe("Test i18n.js", () => {
|
|
||||||
|
|
||||||
it("currentLocale()", () => {
|
|
||||||
const setLanguage = (language) => {
|
|
||||||
Object.defineProperty(window.navigator, 'language', {
|
|
||||||
value: language,
|
|
||||||
writable: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
setLanguage('en-EN');
|
|
||||||
|
|
||||||
expect(currentLocale()).equal("en");
|
|
||||||
|
|
||||||
setLanguage('zh-HK');
|
|
||||||
expect(currentLocale()).equal("zh-HK");
|
|
||||||
|
|
||||||
// Note that in Safari on iOS prior to 10.2, the country code returned is lowercase: "en-us", "fr-fr" etc.
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/Navigator/language
|
|
||||||
setLanguage('zh-hk');
|
|
||||||
expect(currentLocale()).equal("en");
|
|
||||||
|
|
||||||
setLanguage('en-US');
|
|
||||||
expect(currentLocale()).equal("en");
|
|
||||||
|
|
||||||
setLanguage('ja-ZZ');
|
|
||||||
expect(currentLocale()).equal("ja");
|
|
||||||
|
|
||||||
setLanguage('zz-ZZ');
|
|
||||||
expect(currentLocale()).equal("en");
|
|
||||||
|
|
||||||
setLanguage('zz-ZZ');
|
|
||||||
expect(currentLocale()).equal("en");
|
|
||||||
|
|
||||||
setLanguage('en');
|
|
||||||
localStorage.locale = "en";
|
|
||||||
expect(currentLocale()).equal("en");
|
|
||||||
|
|
||||||
localStorage.locale = "zh-HK";
|
|
||||||
expect(currentLocale()).equal("zh-HK");
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
@ -1,41 +0,0 @@
|
|||||||
import { hostNameRegexPattern } from "../../../src/util-frontend";
|
|
||||||
|
|
||||||
describe("Test util-frontend.js", () => {
|
|
||||||
|
|
||||||
describe("hostNameRegexPattern()", () => {
|
|
||||||
it('should return a valid regex for non mqtt hostnames', () => {
|
|
||||||
const regex = new RegExp(hostNameRegexPattern(false));
|
|
||||||
|
|
||||||
expect(regex.test("www.test.com")).to.be.true;
|
|
||||||
expect(regex.test("127.0.0.1")).to.be.true;
|
|
||||||
expect(regex.test("192.168.1.156")).to.be.true;
|
|
||||||
expect(regex.test(" 192.168.1.145")).to.be.false;
|
|
||||||
expect(regex.test("192.168.1.145 ")).to.be.false;
|
|
||||||
expect(regex.test(" fe80::3282:3ff:ae28:592")).to.be.false;
|
|
||||||
expect(regex.test("fe80::3282:3ff:ae28:592 ")).to.be.false;
|
|
||||||
|
|
||||||
["mqtt", "mqtts", "ws", "wss"].forEach(schema => {
|
|
||||||
expect(regex.test(`${schema}://www.test.com`)).to.be.false;
|
|
||||||
expect(regex.test(`${schema}://127.0.0.1`)).to.be.false;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('should return a valid regex for mqtt hostnames', () => {
|
|
||||||
const hostnameString = hostNameRegexPattern(false);
|
|
||||||
console.log('*********', hostnameString, '***********');
|
|
||||||
const regex = new RegExp(hostNameRegexPattern(true));
|
|
||||||
|
|
||||||
expect(regex.test("www.test.com")).to.be.true;
|
|
||||||
expect(regex.test("127.0.0.1")).to.be.true;
|
|
||||||
expect(regex.test("192.168.1.156")).to.be.true;
|
|
||||||
expect(regex.test(" 192.168.1.145")).to.be.false;
|
|
||||||
expect(regex.test("192.168.1.145 ")).to.be.false;
|
|
||||||
expect(regex.test(" fe80::3282:3ff:ae28:592")).to.be.false;
|
|
||||||
expect(regex.test("fe80::3282:3ff:ae28:592 ")).to.be.false;
|
|
||||||
|
|
||||||
["mqtt", "mqtts", "ws", "wss"].forEach(schema => {
|
|
||||||
expect(regex.test(`${schema}://www.test.com`)).to.be.true;
|
|
||||||
expect(regex.test(`${schema}://127.0.0.1`)).to.be.true;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -0,0 +1,43 @@
|
|||||||
|
import { test } from "@playwright/test";
|
||||||
|
import { login, screenshot } from "./util-test";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup
|
||||||
|
*/
|
||||||
|
|
||||||
|
test("setup sqlite", async ({ page }, testInfo) => {
|
||||||
|
await page.goto("./");
|
||||||
|
await page.getByText("SQLite").click();
|
||||||
|
await page.getByRole("button", { name: "Next" }).click();
|
||||||
|
await screenshot(testInfo, page);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("setup admin", async ({ page }, testInfo) => {
|
||||||
|
await page.goto("./");
|
||||||
|
await page.getByPlaceholder("Username").click();
|
||||||
|
await page.getByPlaceholder("Username").fill("admin");
|
||||||
|
await page.getByPlaceholder("Username").press("Tab");
|
||||||
|
await page.getByPlaceholder("Password", { exact: true }).fill("admin123");
|
||||||
|
await page.getByPlaceholder("Password", { exact: true }).press("Tab");
|
||||||
|
await page.getByPlaceholder("Repeat Password").fill("admin123");
|
||||||
|
await page.getByRole("button", { name: "Create" }).click();
|
||||||
|
await screenshot(testInfo, page);
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All other tests should be run after setup
|
||||||
|
*/
|
||||||
|
|
||||||
|
test("login", async ({ page }, testInfo) => {
|
||||||
|
await page.goto("./dashboard");
|
||||||
|
await login(page);
|
||||||
|
await screenshot(testInfo, page);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("logout", async ({ page }, testInfo) => {
|
||||||
|
await page.goto("./dashboard");
|
||||||
|
await login(page);
|
||||||
|
await page.getByText("A", { exact: true }).click();
|
||||||
|
await page.getByRole("button", { name: "Logout" }).click();
|
||||||
|
await screenshot(testInfo, page);
|
||||||
|
});
|
@ -0,0 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* @param {TestInfo} testInfo Test info
|
||||||
|
* @param {Page} page Page
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
export async function screenshot(testInfo, page) {
|
||||||
|
const screenshot = await page.screenshot();
|
||||||
|
await testInfo.attach("screenshot", {
|
||||||
|
body: screenshot,
|
||||||
|
contentType: "image/png"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Page} page Page
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
export async function login(page) {
|
||||||
|
// Login
|
||||||
|
await page.getByPlaceholder("Username").click();
|
||||||
|
await page.getByPlaceholder("Username").fill("admin");
|
||||||
|
await page.getByPlaceholder("Username").press("Tab");
|
||||||
|
await page.getByPlaceholder("Password").fill("admin123");
|
||||||
|
await page.getByLabel("Remember me").check();
|
||||||
|
await page.getByRole("button", { name: "Login" }).click();
|
||||||
|
await page.isVisible("text=Add New Monitor");
|
||||||
|
}
|
Loading…
Reference in new issue