diff --git a/.github/ISSUE_TEMPLATE/ask-for-help.md b/.github/ISSUE_TEMPLATE/ask-for-help.md index c0c8d1e68..8184f8409 100644 --- a/.github/ISSUE_TEMPLATE/ask-for-help.md +++ b/.github/ISSUE_TEMPLATE/ask-for-help.md @@ -9,6 +9,10 @@ assignees: '' **Is it a duplicate question?** Please search in Issues without filters: https://github.com/louislam/uptime-kuma/issues?q= + +**Describe your problem** + + **Info** Uptime Kuma Version: Using Docker?: Yes/No diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 000000000..70266c1f7 --- /dev/null +++ b/babel.config.js @@ -0,0 +1,7 @@ +const config = {}; + +if (process.env.TEST_FRONTEND) { + config.presets = ["@babel/preset-env"]; +} + +module.exports = config; diff --git a/jest-frontend.config.js b/jest-frontend.config.js new file mode 100644 index 000000000..ec4ab8d8e --- /dev/null +++ b/jest-frontend.config.js @@ -0,0 +1,5 @@ +module.exports = { + "rootDir": ".", + "testRegex": "./test/frontend.spec.js", +}; + diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 000000000..6ce5b90a6 --- /dev/null +++ b/jest.config.js @@ -0,0 +1,11 @@ +module.exports = { + "verbose": true, + "preset": "jest-puppeteer", + "globals": { + "__DEV__": true + }, + "testRegex": "./test/e2e.spec.js", + "rootDir": ".", + "testTimeout": 30000, +}; + diff --git a/package.json b/package.json index 1c3467e33..11cb694b0 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,8 @@ "build": "vite build", "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 && jest", + "jest": "node test/prepare-jest.js && npm run jest-frontend && jest ", + "jest-frontend": "cross-env TEST_FRONTEND=1 jest --config=./jest-frontend.config.js", "tsc": "tsc", "vite-preview-dist": "vite preview --host", "build-docker": "npm run build-docker-debian && npm run build-docker-alpine", @@ -99,6 +100,7 @@ }, "devDependencies": { "@babel/eslint-parser": "~7.15.7", + "@babel/preset-env": "^7.15.8", "@types/bootstrap": "~5.1.6", "@vitejs/plugin-legacy": "~1.6.1", "@vitejs/plugin-vue": "~1.9.2", @@ -119,15 +121,5 @@ "stylelint-config-standard": "~22.0.0", "typescript": "~4.4.3", "vite": "~2.6.4" - }, - "jest": { - "verbose": true, - "preset": "jest-puppeteer", - "globals": { - "__DEV__": true - }, - "testRegex": "./test/*.spec.js", - "rootDir": ".", - "testTimeout": 30000 } } diff --git a/src/components/Status.vue b/src/components/Status.vue index a4436e22a..a3916adce 100644 --- a/src/components/Status.vue +++ b/src/components/Status.vue @@ -11,18 +11,18 @@ export default { computed: { color() { if (this.status === 0) { - return "danger" + return "danger"; } if (this.status === 1) { - return "primary" + return "primary"; } if (this.status === 2) { - return "warning" + return "warning"; } - return "secondary" + return "secondary"; }, text() { @@ -41,11 +41,11 @@ export default { return this.$t("Unknown"); }, }, -} +}; diff --git a/src/i18n.js b/src/i18n.js index 53a73124f..ca47742e6 100644 --- a/src/i18n.js +++ b/src/i18n.js @@ -49,7 +49,10 @@ const languageList = { const rtlLangs = ["fa"]; -export const currentLocale = () => localStorage.locale || "en"; +export const currentLocale = () => localStorage.locale + || languageList[navigator.language] && navigator.language + || languageList[navigator.language.substring(0, 2)] && navigator.language.substring(0, 2) + || "en"; export const localeDirection = () => { return rtlLangs.includes(currentLocale()) ? "rtl" : "ltr"; diff --git a/src/main.js b/src/main.js index 79ba2d1dd..14b87f49d 100644 --- a/src/main.js +++ b/src/main.js @@ -43,3 +43,9 @@ app.component("Editable", contenteditable); app.component("FontAwesomeIcon", FontAwesomeIcon); app.mount("#app"); + +// Expose the vue instance for development +if (process.env.NODE_ENV === "development") { + console.log("Dev Only: window.app is the vue instance"); + window.app = app._instance; +} diff --git a/src/util.js b/src/util.js index 64ac2f6f6..7fb50c5b0 100644 --- a/src/util.js +++ b/src/util.js @@ -74,7 +74,7 @@ class TimeLogger { this.startTime = dayjs().valueOf(); } print(name) { - if (exports.isDev && process && process.env.TIMELOGGER === "1") { + if (exports.isDev && process.env.TIMELOGGER === "1") { console.log(name + ": " + (dayjs().valueOf() - this.startTime) + "ms"); } } diff --git a/src/util.ts b/src/util.ts index 450050490..6e911998d 100644 --- a/src/util.ts +++ b/src/util.ts @@ -86,7 +86,7 @@ export class TimeLogger { } print(name: string) { - if (isDev && process && process.env.TIMELOGGER === "1") { + if (isDev && process.env.TIMELOGGER === "1") { console.log(name + ": " + (dayjs().valueOf() - this.startTime) + "ms") } } diff --git a/test/test.spec.js b/test/e2e.spec.js similarity index 94% rename from test/test.spec.js rename to test/e2e.spec.js index 91c8459bd..03920b306 100644 --- a/test/test.spec.js +++ b/test/e2e.spec.js @@ -36,7 +36,7 @@ describe("Init", () => { }); it(`should be titled "${title}"`, async () => { - await expect(page.title()).resolves.toMatch(title); + await expect(page.title()).resolves.toEqual(title); }); // Setup Page @@ -75,11 +75,11 @@ describe("Init", () => { await page.select("#language", "zh-HK"); let languageTitle = await page.evaluate(() => document.querySelector("[for=language]").innerText); - expect(languageTitle).toMatch("語言"); + expect(languageTitle).toEqual("語言"); await page.select("#language", "en"); languageTitle = await page.evaluate(() => document.querySelector("[for=language]").innerText); - expect(languageTitle).toMatch("Language"); + expect(languageTitle).toEqual("Language"); }); it("Change Theme", async () => { @@ -103,21 +103,21 @@ describe("Init", () => { it("Search Engine Visibility", async () => { // Default let res = await axios.get(baseURL + "/robots.txt"); - expect(res.data).toMatch("Disallow: /"); + expect(res.data).toContain("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: /"); + expect(res.data).not.toContain("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: /"); + expect(res.data).toContain("Disallow: /"); }); it("Entry Page", async () => { @@ -218,7 +218,7 @@ describe("Init", () => { await page.goto(baseURL + "/status"); }); it(`should be titled "${title}"`, async () => { - await expect(page.title()).resolves.toMatch(title); + await expect(page.title()).resolves.toEqual(title); }); }); }); diff --git a/test/frontend.spec.js b/test/frontend.spec.js new file mode 100644 index 000000000..63121a6ba --- /dev/null +++ b/test/frontend.spec.js @@ -0,0 +1,42 @@ +// eslint-disable-next-line no-global-assign +global.localStorage = {}; +global.navigator = { + language: "en" +}; + +const { currentLocale } = require("../src/i18n"); + +describe("Test i18n.js", () => { + + it("currentLocale()", () => { + expect(currentLocale()).toEqual("en"); + + navigator.language = "zh-HK"; + expect(currentLocale()).toEqual("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 + navigator.language = "zh-hk"; + expect(currentLocale()).toEqual("en"); + + navigator.language = "en-US"; + expect(currentLocale()).toEqual("en"); + + navigator.language = "ja-ZZ"; + expect(currentLocale()).toEqual("ja"); + + navigator.language = "zz"; + expect(currentLocale()).toEqual("en"); + + navigator.language = "zz-ZZ"; + expect(currentLocale()).toEqual("en"); + + localStorage.locale = "en"; + expect(currentLocale()).toEqual("en"); + + localStorage.locale = "zh-HK"; + expect(currentLocale()).toEqual("zh-HK"); + }); + +}); + diff --git a/test/test_install_script/ubuntu.dockerfile b/test/test_install_script/ubuntu.dockerfile index 07d8a25a4..fc9dcd3f4 100644 --- a/test/test_install_script/ubuntu.dockerfile +++ b/test/test_install_script/ubuntu.dockerfile @@ -6,5 +6,4 @@ FROM ubuntu # RUN ln -s /usr/bin/nodejs /usr/bin/node # RUN node -v -COPY ./install.sh . -RUN bash install.sh local /opt/uptime-kuma 3000 0.0.0.0 +RUN curl -o kuma_install.sh http://git.kuma.pet/install.sh && bash kuma_install.sh local /opt/uptime-kuma 3000 0.0.0.0