mirror of
https://github.com/louislam/uptime-kuma.git
synced 2024-11-23 23:04:04 +00:00
Merge pull request #1780 from tamasmagyar/test/add-cypress-tests
test: added cypress framework and tests for setup page
This commit is contained in:
commit
b22176d218
18 changed files with 138 additions and 10 deletions
|
@ -1,6 +1,7 @@
|
||||||
/.idea
|
/.idea
|
||||||
/node_modules
|
/node_modules
|
||||||
/data
|
/data
|
||||||
|
/cypress
|
||||||
/out
|
/out
|
||||||
/test
|
/test
|
||||||
/kubernetes
|
/kubernetes
|
||||||
|
|
16
.github/workflows/auto-test.yml
vendored
16
.github/workflows/auto-test.yml
vendored
|
@ -50,3 +50,19 @@ jobs:
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
- run: npm install
|
- run: npm install
|
||||||
- run: npm run lint
|
- run: npm run lint
|
||||||
|
|
||||||
|
e2e-tests:
|
||||||
|
needs: [ check-linters ]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- run: git config --global core.autocrlf false # Mainly for Windows
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Use Node.js 14
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: 14
|
||||||
|
cache: 'npm'
|
||||||
|
- run: npm install
|
||||||
|
- run: npm run build
|
||||||
|
- run: npm run cy:test
|
||||||
|
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -13,3 +13,6 @@ dist-ssr
|
||||||
/out
|
/out
|
||||||
/tmp
|
/tmp
|
||||||
.env
|
.env
|
||||||
|
|
||||||
|
cypress/videos
|
||||||
|
cypress/screenshots
|
||||||
|
|
15
cypress.config.ts
Normal file
15
cypress.config.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import { defineConfig } from "cypress";
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
e2e: {
|
||||||
|
baseUrl: "http://localhost:3002",
|
||||||
|
defaultCommandTimeout: 10000,
|
||||||
|
pageLoadTimeout: 60000,
|
||||||
|
viewportWidth: 1920,
|
||||||
|
viewportHeight: 1080,
|
||||||
|
specPattern: ["cypress/e2e/setup.cy.ts", "cypress/e2e/**/*.ts"],
|
||||||
|
},
|
||||||
|
env: {
|
||||||
|
baseUrl: "http://localhost:3002",
|
||||||
|
},
|
||||||
|
});
|
24
cypress/e2e/setup.cy.ts
Normal file
24
cypress/e2e/setup.cy.ts
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import { actor } from "../support/actors/actor";
|
||||||
|
import { DEFAULT_USER_DATA } from "../support/const/user-data";
|
||||||
|
import { DashboardPage } from "../support/pages/dasboard-page";
|
||||||
|
import { SetupPage } from "../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.url);
|
||||||
|
actor.setupTask.fillAndSubmitSetupForm(
|
||||||
|
DEFAULT_USER_DATA.username,
|
||||||
|
DEFAULT_USER_DATA.password,
|
||||||
|
DEFAULT_USER_DATA.password
|
||||||
|
);
|
||||||
|
|
||||||
|
cy.url().should("be.equal", DashboardPage.url);
|
||||||
|
cy.get('[role="alert"]')
|
||||||
|
.should("be.visible")
|
||||||
|
.and("contain.text", "Added Successfully.");
|
||||||
|
});
|
||||||
|
});
|
0
cypress/plugins/index.js
Normal file
0
cypress/plugins/index.js
Normal file
8
cypress/support/actors/actor.ts
Normal file
8
cypress/support/actors/actor.ts
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import { SetupTask } from "../tasks/setup-task";
|
||||||
|
|
||||||
|
class Actor {
|
||||||
|
setupTask: SetupTask = new SetupTask();
|
||||||
|
}
|
||||||
|
|
||||||
|
const actor = new Actor();
|
||||||
|
export { actor };
|
0
cypress/support/commands.ts
Normal file
0
cypress/support/commands.ts
Normal file
4
cypress/support/const/user-data.ts
Normal file
4
cypress/support/const/user-data.ts
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
export const DEFAULT_USER_DATA = {
|
||||||
|
username: "testuser",
|
||||||
|
password: "testuser123",
|
||||||
|
};
|
1
cypress/support/e2e.ts
Normal file
1
cypress/support/e2e.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
import "./commands";
|
3
cypress/support/pages/dasboard-page.ts
Normal file
3
cypress/support/pages/dasboard-page.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export const DashboardPage = {
|
||||||
|
url: Cypress.env("baseUrl") + "/dashboard",
|
||||||
|
};
|
7
cypress/support/pages/setup-page.ts
Normal file
7
cypress/support/pages/setup-page.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
export const 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"]',
|
||||||
|
};
|
15
cypress/support/tasks/setup-task.ts
Normal file
15
cypress/support/tasks/setup-task.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import { SetupPage } from "../pages/setup-page";
|
||||||
|
|
||||||
|
export class SetupTask {
|
||||||
|
fillAndSubmitSetupForm(
|
||||||
|
username: string,
|
||||||
|
password: string,
|
||||||
|
passwordRepeat: string
|
||||||
|
) {
|
||||||
|
cy.get(SetupPage.usernameInput).type(username);
|
||||||
|
cy.get(SetupPage.passWordInput).type(password);
|
||||||
|
cy.get(SetupPage.passwordRepeatInput).type(passwordRepeat);
|
||||||
|
|
||||||
|
cy.get(SetupPage.submitSetupForm).click();
|
||||||
|
}
|
||||||
|
}
|
|
@ -60,7 +60,9 @@
|
||||||
"release-beta": "node extra/beta/update-version.js && npm run build && node ./extra/env2arg.js docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:$VERSION -t louislam/uptime-kuma:beta . --target release --push && node ./extra/press-any-key.js && npm run upload-artifacts",
|
"release-beta": "node extra/beta/update-version.js && npm run build && node ./extra/env2arg.js docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:$VERSION -t louislam/uptime-kuma:beta . --target release --push && node ./extra/press-any-key.js && npm run upload-artifacts",
|
||||||
"git-remove-tag": "git tag -d",
|
"git-remove-tag": "git tag -d",
|
||||||
"build-dist-and-restart": "npm run build && npm run start-server-dev",
|
"build-dist-and-restart": "npm run build && npm run start-server-dev",
|
||||||
"start-pr-test": "node extra/checkout-pr.js && npm install && npm run dev"
|
"start-pr-test": "node extra/checkout-pr.js && npm install && npm run dev",
|
||||||
|
"cy:test": "node test/prepare-test-server.js && node server/server.js --port=3002 --data-dir=./data/test/ --e2e",
|
||||||
|
"cy:run": "npx cypress run --browser chrome --headless"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@louislam/sqlite3": "~15.0.6",
|
"@louislam/sqlite3": "~15.0.6",
|
||||||
|
@ -130,6 +132,8 @@
|
||||||
"concurrently": "^7.1.0",
|
"concurrently": "^7.1.0",
|
||||||
"core-js": "~3.18.3",
|
"core-js": "~3.18.3",
|
||||||
"cross-env": "~7.0.3",
|
"cross-env": "~7.0.3",
|
||||||
|
"cypress": "^10.1.0",
|
||||||
|
"delay": "^5.0.0",
|
||||||
"dns2": "~2.0.1",
|
"dns2": "~2.0.1",
|
||||||
"eslint": "~8.14.0",
|
"eslint": "~8.14.0",
|
||||||
"eslint-plugin-vue": "~8.7.1",
|
"eslint-plugin-vue": "~8.7.1",
|
||||||
|
|
|
@ -61,7 +61,7 @@ log.info("server", "Importing this project modules");
|
||||||
log.debug("server", "Importing Monitor");
|
log.debug("server", "Importing Monitor");
|
||||||
const Monitor = require("./model/monitor");
|
const Monitor = require("./model/monitor");
|
||||||
log.debug("server", "Importing Settings");
|
log.debug("server", "Importing Settings");
|
||||||
const { getSettings, setSettings, setting, initJWTSecret, checkLogin, startUnitTest, FBSD, doubleCheckPassword } = require("./util-server");
|
const { getSettings, setSettings, setting, initJWTSecret, checkLogin, startUnitTest, FBSD, doubleCheckPassword, startE2eTests } = require("./util-server");
|
||||||
|
|
||||||
log.debug("server", "Importing Notification");
|
log.debug("server", "Importing Notification");
|
||||||
const { Notification } = require("./notification");
|
const { Notification } = require("./notification");
|
||||||
|
@ -112,6 +112,7 @@ const twoFAVerifyOptions = {
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
*/
|
*/
|
||||||
const testMode = !!args["test"] || false;
|
const testMode = !!args["test"] || false;
|
||||||
|
const e2eTestMode = !!args["e2e"] || false;
|
||||||
|
|
||||||
if (config.demoMode) {
|
if (config.demoMode) {
|
||||||
log.info("server", "==== Demo Mode ====");
|
log.info("server", "==== Demo Mode ====");
|
||||||
|
@ -1486,6 +1487,10 @@ let needSetup = false;
|
||||||
if (testMode) {
|
if (testMode) {
|
||||||
startUnitTest();
|
startUnitTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (e2eTestMode) {
|
||||||
|
startE2eTests();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
initBackgroundJobs(args);
|
initBackgroundJobs(args);
|
||||||
|
|
|
@ -573,6 +573,26 @@ exports.startUnitTest = async () => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Start end-to-end tests */
|
||||||
|
exports.startE2eTests = async () => {
|
||||||
|
console.log("Starting unit test...");
|
||||||
|
const npm = /^win/.test(process.platform) ? "npm.cmd" : "npm";
|
||||||
|
const child = childProcess.spawn(npm, [ "run", "cy:run" ]);
|
||||||
|
|
||||||
|
child.stdout.on("data", (data) => {
|
||||||
|
console.log(data.toString());
|
||||||
|
});
|
||||||
|
|
||||||
|
child.stderr.on("data", (data) => {
|
||||||
|
console.log(data.toString());
|
||||||
|
});
|
||||||
|
|
||||||
|
child.on("close", function (code) {
|
||||||
|
console.log("Jest exit code: " + code);
|
||||||
|
process.exit(code);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert unknown string to UTF8
|
* Convert unknown string to UTF8
|
||||||
* @param {Uint8Array} body Buffer
|
* @param {Uint8Array} body Buffer
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="form-container">
|
<div class="form-container" data-cy="setup-form">
|
||||||
<div class="form">
|
<div class="form">
|
||||||
<form @submit.prevent="submit">
|
<form @submit.prevent="submit">
|
||||||
<div>
|
<div>
|
||||||
|
@ -23,21 +23,21 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-floating mt-3">
|
<div class="form-floating mt-3">
|
||||||
<input id="floatingInput" v-model="username" type="text" class="form-control" placeholder="Username" required>
|
<input id="floatingInput" v-model="username" type="text" class="form-control" placeholder="Username" required data-cy="username-input">
|
||||||
<label for="floatingInput">{{ $t("Username") }}</label>
|
<label for="floatingInput">{{ $t("Username") }}</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-floating mt-3">
|
<div class="form-floating mt-3">
|
||||||
<input id="floatingPassword" v-model="password" type="password" class="form-control" placeholder="Password" required>
|
<input id="floatingPassword" v-model="password" type="password" class="form-control" placeholder="Password" required data-cy="password-input">
|
||||||
<label for="floatingPassword">{{ $t("Password") }}</label>
|
<label for="floatingPassword">{{ $t("Password") }}</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-floating mt-3">
|
<div class="form-floating mt-3">
|
||||||
<input id="repeat" v-model="repeatPassword" type="password" class="form-control" placeholder="Repeat Password" required>
|
<input id="repeat" v-model="repeatPassword" type="password" class="form-control" placeholder="Repeat Password" required data-cy="password-repeat-input">
|
||||||
<label for="repeat">{{ $t("Repeat Password") }}</label>
|
<label for="repeat">{{ $t("Repeat Password") }}</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button class="w-100 btn btn-primary mt-3" type="submit" :disabled="processing">
|
<button class="w-100 btn btn-primary mt-3" type="submit" :disabled="processing" data-cy="submit-setup-form">
|
||||||
{{ $t("Create") }}
|
{{ $t("Create") }}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -11,9 +11,11 @@
|
||||||
"removeComments": false,
|
"removeComments": false,
|
||||||
"preserveConstEnums": true,
|
"preserveConstEnums": true,
|
||||||
"sourceMap": false,
|
"sourceMap": false,
|
||||||
"strict": true
|
"strict": true,
|
||||||
|
"types": ["cypress"]
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"./src/util.ts"
|
"./src/util.ts",
|
||||||
]
|
],
|
||||||
|
"include": ["cypress/**/*.ts"]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue