mirror of
https://github.com/openobserve/openobserve.git
synced 2026-11-04 00:08:55 +00:00
fix: Updated UI unit test setup (#6520)
Co-authored-by: Sai Nikhil <nikhil@openobserve.ai>
This commit is contained in:
co-authored by
Sai Nikhil
parent
c8bee3ff9f
commit
666dfcdb62
@@ -245,7 +245,7 @@ export class LogsPage {
|
||||
async kubernetesContainerNameJoin() {
|
||||
await this.page
|
||||
.locator('[data-test="logs-search-bar-query-editor"]')
|
||||
.getByLabel("Editor content;Press Alt+F1")
|
||||
.locator(".inputarea")
|
||||
.fill('SELECT a.kubernetes_container_name , b.kubernetes_container_name FROM "default" as a join "e2e_automate" as b on a.kubernetes_container_name = b.kubernetes_container_name');
|
||||
await this.page.waitForTimeout(5000);
|
||||
}
|
||||
@@ -253,7 +253,7 @@ export class LogsPage {
|
||||
async kubernetesContainerNameJoinLimit() {
|
||||
await this.page
|
||||
.locator('[data-test="logs-search-bar-query-editor"]')
|
||||
.getByLabel("Editor content;Press Alt+F1")
|
||||
.locator(".inputarea")
|
||||
.fill('SELECT a.kubernetes_container_name , b.kubernetes_container_name FROM "default" as a join "e2e_automate" as b on a.kubernetes_container_name = b.kubernetes_container_name LIMIT 10');
|
||||
await this.page.waitForTimeout(5000);
|
||||
}
|
||||
@@ -262,7 +262,7 @@ export class LogsPage {
|
||||
async kubernetesContainerNameJoinLike() {
|
||||
await this.page
|
||||
.locator('[data-test="logs-search-bar-query-editor"]')
|
||||
.getByLabel("Editor content;Press Alt+F1")
|
||||
.locator(".inputarea")
|
||||
.fill('SELECT a.kubernetes_container_name , b.kubernetes_container_name FROM "default" as a join "e2e_automate" as b on a.kubernetes_container_name = b.kubernetes_container_name WHERE a.kubernetes_container_name LIKE "%ziox%"');
|
||||
await this.page.waitForTimeout(5000);
|
||||
}
|
||||
@@ -270,7 +270,7 @@ export class LogsPage {
|
||||
async kubernetesContainerNameLeftJoin() {
|
||||
await this.page
|
||||
.locator('[data-test="logs-search-bar-query-editor"]')
|
||||
.getByLabel("Editor content;Press Alt+F1")
|
||||
.locator(".inputarea")
|
||||
.fill('SELECT a.kubernetes_container_name , b.kubernetes_container_name FROM "default" as a LEFT JOIN "e2e_automate" as b on a.kubernetes_container_name = b.kubernetes_container_name');
|
||||
await this.page.waitForTimeout(5000);
|
||||
}
|
||||
@@ -278,7 +278,7 @@ export class LogsPage {
|
||||
async kubernetesContainerNameRightJoin() {
|
||||
await this.page
|
||||
.locator('[data-test="logs-search-bar-query-editor"]')
|
||||
.getByLabel("Editor content;Press Alt+F1")
|
||||
.locator(".inputarea")
|
||||
.fill('SELECT a.kubernetes_container_name , b.kubernetes_container_name FROM "default" as a RIGHT JOIN "e2e_automate" as b on a.kubernetes_container_name = b.kubernetes_container_name');
|
||||
await this.page.waitForTimeout(5000);
|
||||
}
|
||||
@@ -286,7 +286,7 @@ export class LogsPage {
|
||||
async kubernetesContainerNameFullJoin() {
|
||||
await this.page
|
||||
.locator('[data-test="logs-search-bar-query-editor"]')
|
||||
.getByLabel("Editor content;Press Alt+F1")
|
||||
.locator(".inputarea")
|
||||
.fill('SELECT a.kubernetes_container_name , b.kubernetes_container_name FROM "default" as a FULL JOIN "e2e_automate" as b on a.kubernetes_container_name = b.kubernetes_container_name');
|
||||
await this.page.waitForTimeout(5000);
|
||||
}
|
||||
@@ -466,7 +466,7 @@ async selectIndexStreamDefault() {
|
||||
}
|
||||
|
||||
async clearAndFillQueryEditor(query) {
|
||||
const editor = this.page.locator('[data-test="logs-search-bar-query-editor"]').getByLabel('Editor content;Press Alt+F1');
|
||||
const editor = this.page.locator('[data-test="logs-search-bar-query-editor"]').locator(".inputarea");
|
||||
await editor.fill(''); // Clear the editor
|
||||
await this.page.waitForTimeout(1000); // Optional: adjust or remove as per your needs
|
||||
await editor.fill(query); // Fill with the new query
|
||||
|
||||
@@ -95,7 +95,7 @@ test.describe("Sanity Tests", () => { let dashboardPage
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
await page.locator('[data-test="dashboard-panel-error-bar-icon"]').click();
|
||||
await page.locator('[data-test="dashboard-panel-query-editor"]').getByRole("textbox", { name: "Editor content;Press Alt+F1" }).fill('select * from "e2e_automate"');
|
||||
await page.locator('[data-test="dashboard-panel-query-editor"]').locator('.inputarea').fill('select * from "e2e_automate"');
|
||||
await page.locator('[data-test="dashboard-apply"]').click();
|
||||
await page.waitForTimeout(3000);
|
||||
await expect(page.getByText("Unsafe code detected: Access to 'document' is not allowed")).toBeVisible();
|
||||
@@ -114,7 +114,7 @@ test("Add line JSON in Monaco Editor", async ({ page }) => {
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
await page.locator('[data-test="dashboard-panel-error-bar-icon"]').click();
|
||||
await page.locator('[data-test="dashboard-panel-query-editor"]').getByRole("textbox", { name: "Editor content;Press Alt+F1" }).fill('select * from "e2e_automate"');
|
||||
await page.locator('[data-test="dashboard-panel-query-editor"]').locator('.inputarea').fill('select * from "e2e_automate"');
|
||||
await page.waitForTimeout(3000);
|
||||
await page.locator('[data-test="dashboard-apply"]').click();
|
||||
await page.waitForTimeout(3000);
|
||||
|
||||
@@ -405,7 +405,7 @@ test.describe("dashboard UI testcases", () => {
|
||||
.click();
|
||||
await page
|
||||
.locator('[data-test="dashboard-vrl-function-editor"]')
|
||||
.getByLabel("Editor content;Press Alt+F1")
|
||||
.locator('.inputarea')
|
||||
.fill(".vrl=100");
|
||||
|
||||
await page.waitForTimeout(2000);
|
||||
@@ -484,7 +484,7 @@ test.describe("dashboard UI testcases", () => {
|
||||
.click();
|
||||
await page
|
||||
.locator('[data-test="dashboard-vrl-function-editor"]')
|
||||
.getByLabel("Editor content;Press Alt+F1")
|
||||
.locator('.inputarea')
|
||||
.fill(".vrl=100");
|
||||
|
||||
await page.locator('[data-test="selected-chart-table-item"] img').click();
|
||||
|
||||
@@ -305,7 +305,7 @@ test.describe("dashboard UI testcases", () => {
|
||||
await page.locator(".view-line").first().click();
|
||||
await page
|
||||
.locator('[data-test="dashboard-panel-query-editor"]')
|
||||
.getByLabel("Editor content;Press Alt+F1")
|
||||
.locator('.inputarea')
|
||||
.fill(
|
||||
'SELECT histogram(_timestamp) as "x_axis_1", count(_timestamp) as "y_axis_1", kubernetes_container_name as "breakdown_1" FROM "e2e_automate" GROUP BY x_axis_1, breakdown_1'
|
||||
);
|
||||
|
||||
@@ -131,7 +131,7 @@ test.describe(" visualize UI testcases", () => {
|
||||
.click();
|
||||
await page
|
||||
.locator("#fnEditor")
|
||||
.getByLabel("Editor content;Press Alt+F1")
|
||||
.locator('.inputarea')
|
||||
.fill(".vrl12=123");
|
||||
|
||||
await page.waitForTimeout(3000);
|
||||
@@ -181,7 +181,7 @@ test.describe(" visualize UI testcases", () => {
|
||||
.click();
|
||||
await page
|
||||
.locator("#fnEditor")
|
||||
.getByLabel("Editor content;Press Alt+F1")
|
||||
.locator('.inputarea')
|
||||
.fill(".vrL=1000");
|
||||
await page.waitForTimeout(3000);
|
||||
|
||||
@@ -240,7 +240,7 @@ test.describe(" visualize UI testcases", () => {
|
||||
.click();
|
||||
await page
|
||||
.locator("#fnEditor")
|
||||
.getByLabel("Editor content;Press Alt+F1")
|
||||
.locator('.inputarea')
|
||||
.fill(".VRL=1000");
|
||||
|
||||
await page.waitForTimeout(3000);
|
||||
@@ -326,7 +326,7 @@ test.describe(" visualize UI testcases", () => {
|
||||
.click();
|
||||
await page
|
||||
.locator("#fnEditor")
|
||||
.getByLabel("Editor content;Press Alt+F1")
|
||||
.locator('.inputarea')
|
||||
.fill(".vrl=11abc");
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
@@ -338,11 +338,11 @@ test.describe(" visualize UI testcases", () => {
|
||||
|
||||
await page
|
||||
.locator("#fnEditor")
|
||||
.getByLabel("Editor content;Press Alt+F1")
|
||||
.locator('.inputarea')
|
||||
.press("Control+a");
|
||||
await page
|
||||
.locator("#fnEditor")
|
||||
.getByLabel("Editor content;Press Alt+F1")
|
||||
.locator('.inputarea')
|
||||
.fill(".vrl=123");
|
||||
|
||||
await page.waitForTimeout(3000);
|
||||
@@ -392,7 +392,7 @@ test.describe(" visualize UI testcases", () => {
|
||||
.click();
|
||||
await page
|
||||
.locator("#fnEditor")
|
||||
.getByLabel("Editor content;Press Alt+F1")
|
||||
.locator('.inputarea')
|
||||
.fill(".vrl=100");
|
||||
|
||||
await page.waitForTimeout(3000);
|
||||
@@ -432,7 +432,7 @@ test.describe(" visualize UI testcases", () => {
|
||||
.click();
|
||||
await page
|
||||
.locator("#fnEditor")
|
||||
.getByLabel("Editor content;Press Alt+F1")
|
||||
.locator('.inputarea')
|
||||
.fill(".vrlsanity=100");
|
||||
|
||||
await page.waitForTimeout(3000);
|
||||
@@ -451,7 +451,7 @@ test.describe(" visualize UI testcases", () => {
|
||||
.click();
|
||||
await page
|
||||
.locator("#fnEditor")
|
||||
.getByLabel("Editor content;Press Alt+F1")
|
||||
.locator('.inputarea')
|
||||
.press("Control+a");
|
||||
await page.locator('[data-test="logs-search-bar-refresh-btn"]').click();
|
||||
await page.locator('[data-test="logs-search-bar-refresh-btn"]').click();
|
||||
@@ -471,7 +471,7 @@ test.describe(" visualize UI testcases", () => {
|
||||
.click();
|
||||
await page
|
||||
.locator("#fnEditor")
|
||||
.getByLabel("Editor content;Press Alt+F1")
|
||||
.locator('.inputarea')
|
||||
.fill(".vrl=123");
|
||||
|
||||
await page.waitForTimeout(3000);
|
||||
@@ -527,7 +527,7 @@ test.describe(" visualize UI testcases", () => {
|
||||
.click();
|
||||
await page
|
||||
.locator("#fnEditor")
|
||||
.getByLabel("Editor content;Press Alt+F1")
|
||||
.locator('.inputarea')
|
||||
.fill(".VRLsanity=1000");
|
||||
await page.waitForTimeout(3000);
|
||||
|
||||
|
||||
@@ -403,7 +403,7 @@ test.describe(" visualize UI testcases", () => {
|
||||
// Enter an invalid query into the search bar
|
||||
await page
|
||||
.locator('[data-test="logs-search-bar-query-editor"]')
|
||||
.getByLabel("Editor content;Press Alt+F1")
|
||||
.locator('.inputarea')
|
||||
.fill("select from user whare ID =1");
|
||||
|
||||
// Refresh the search
|
||||
|
||||
@@ -214,8 +214,9 @@ test.describe("Enrichment data testcases", () => {
|
||||
}
|
||||
|
||||
// Explore the file
|
||||
await page.getByRole("button", { name: "Explore" }).click();
|
||||
await page.locator("#fnEditor").getByLabel("Editor content;Press Alt+F1")
|
||||
await page.locator(`[data-test="${fileName}-explore-btn"]`).click();
|
||||
await page.waitForSelector('[data-test="logs-vrl-function-editor"]');
|
||||
await page.locator('[data-test="logs-vrl-function-editor"]').locator('.inputarea')
|
||||
.fill(`
|
||||
abc, err = get_enrichment_table_record("${fileName}", {
|
||||
"protocol_number": to_string!(.protocol_number)
|
||||
|
||||
@@ -124,7 +124,7 @@ test.describe("Logs UI testcases", () => {
|
||||
await applyQueryButton(page);
|
||||
|
||||
|
||||
await page.locator('#fnEditor').getByLabel('Editor content;Press Alt+F1').fill('.a=2');
|
||||
await page.locator('#fnEditor').locator('.inputarea').fill('.a=2');
|
||||
await page.waitForTimeout(1000);
|
||||
await applyQueryButton(page);
|
||||
const warningElement = page.locator('text=warning Query execution');
|
||||
@@ -401,7 +401,7 @@ test.describe("Logs UI testcases", () => {
|
||||
await page.locator('[data-test="logs-search-bar-refresh-btn"]').click();
|
||||
await page.locator('[data-test="logs-search-bar-function-dropdown"] button').filter({ hasText: 'save' }).click();
|
||||
await page.locator('#fnEditor > .monaco-editor > .overflow-guard > .monaco-scrollable-element > .lines-content > .view-lines > .view-line').click();
|
||||
await page.locator('#fnEditor').getByLabel('Editor content;Press Alt+F1').fill('.a=2');
|
||||
await page.locator('#fnEditor').locator('.inputarea').fill('.a=2');
|
||||
await page.waitForTimeout(1000);
|
||||
await page.locator('[data-test="logs-search-bar-function-dropdown"] button').filter({ hasText: 'save' }).click();
|
||||
await page.locator('[data-test="saved-function-name-input"]').click();
|
||||
@@ -420,7 +420,7 @@ test.describe("Logs UI testcases", () => {
|
||||
|
||||
test('should display click save directly while creating a function', async ({ page }) => {
|
||||
await page.waitForTimeout(1000);
|
||||
await page.locator('#fnEditor').getByLabel('Editor content;Press Alt+F1').fill('.a=2');
|
||||
await page.locator('#fnEditor').locator('.inputarea').fill('.a=2');
|
||||
await page.waitForTimeout(1000);
|
||||
await page.locator('[data-test="logs-search-bar-function-dropdown"] button').filter({ hasText: 'save' }).click();
|
||||
await page.locator('[data-test="saved-view-dialog-save-btn"]').click();
|
||||
@@ -429,7 +429,7 @@ test.describe("Logs UI testcases", () => {
|
||||
|
||||
test('should display error on adding only blank spaces under function name', async ({ page }) => {
|
||||
await page.waitForTimeout(1000);
|
||||
await page.locator('#fnEditor').getByLabel('Editor content;Press Alt+F1').fill('.a=2');
|
||||
await page.locator('#fnEditor').locator('.inputarea').fill('.a=2');
|
||||
await page.waitForTimeout(1000);
|
||||
await page.locator('[data-test="logs-search-bar-function-dropdown"] button').filter({ hasText: 'save' }).click();
|
||||
await page.locator('[data-test="saved-function-name-input"]').fill(' ');
|
||||
@@ -440,7 +440,7 @@ test.describe("Logs UI testcases", () => {
|
||||
|
||||
test('should display error on adding invalid characters under function name', async ({ page }) => {
|
||||
await page.waitForTimeout(1000);
|
||||
await page.locator('#fnEditor').getByLabel('Editor content;Press Alt+F1').fill('.a=2');
|
||||
await page.locator('#fnEditor').locator('.inputarea').fill('.a=2');
|
||||
await page.waitForTimeout(1000);
|
||||
await page.locator('[data-test="logs-search-bar-function-dropdown"] button').filter({ hasText: 'save' }).click();
|
||||
await page.locator('[data-test="saved-function-name-input"]').fill('e2e@@@');
|
||||
@@ -450,7 +450,7 @@ test.describe("Logs UI testcases", () => {
|
||||
|
||||
test('should display added function on switching between tabs and again navigate to log', async ({ page }) => {
|
||||
await page.waitForTimeout(1000);
|
||||
await page.locator('#fnEditor').getByLabel('Editor content;Press Alt+F1').fill('.a=2');
|
||||
await page.locator('#fnEditor').locator('.inputarea').fill('.a=2');
|
||||
await page.waitForTimeout(1000);
|
||||
await page.locator('[data-test="logs-search-bar-refresh-btn"]').click();
|
||||
await page.locator('[data-test="menu-link-\\/metrics-item"]').click();
|
||||
@@ -496,7 +496,7 @@ test.describe("Logs UI testcases", () => {
|
||||
test.skip('should display results for search around after adding function', async ({ page }) => {
|
||||
await page.waitForTimeout(1000);
|
||||
await page.locator('#fnEditor > .monaco-editor > .overflow-guard > .monaco-scrollable-element > .lines-content > .view-lines > .view-line').click();
|
||||
await page.locator('#fnEditor').getByLabel('Editor content;Press Alt+F1').fill('.a=1');
|
||||
await page.locator('#fnEditor').locator('.inputarea').fill('.a=1');
|
||||
await page.waitForTimeout(1000);
|
||||
await page.locator('[data-test="logs-search-bar-refresh-btn"]').click();
|
||||
await page.locator('[data-test="log-table-column-3-source"]').getByText('{"_timestamp":').click();
|
||||
|
||||
@@ -134,7 +134,7 @@ async function multistreamselect(page) {
|
||||
|
||||
test("should add a function and display it in streams", async ({ page }) => {
|
||||
await multistreamselect(page);
|
||||
await page.locator('#fnEditor').getByLabel('Editor content;Press Alt+F1').fill('.a=2');
|
||||
await page.locator('#fnEditor').locator('.inputarea').fill('.a=2');
|
||||
await page.waitForTimeout(1000);
|
||||
await applyQueryButton(page);
|
||||
await page
|
||||
|
||||
@@ -233,7 +233,7 @@ test.describe("Sanity testcases", () => {
|
||||
.click();
|
||||
await page
|
||||
.locator('[data-test="logs-search-bar-query-editor"]')
|
||||
.getByLabel("Editor content;Press Alt+F1")
|
||||
.locator('.inputarea')
|
||||
.fill('SELECT * FROM "e2e_automate" ORDER BY _timestamp DESC limit 5');
|
||||
await page.waitForTimeout(2000);
|
||||
await page
|
||||
@@ -265,7 +265,7 @@ test.describe("Sanity testcases", () => {
|
||||
.click();
|
||||
await page
|
||||
.locator("#fnEditor")
|
||||
.getByLabel("Editor content;Press Alt+F1")
|
||||
.locator('.inputarea')
|
||||
.fill(".a=2");
|
||||
await page.waitForTimeout(1000);
|
||||
await page
|
||||
@@ -300,13 +300,13 @@ test.describe("Sanity testcases", () => {
|
||||
await page.getByLabel("Name").click();
|
||||
await page.getByLabel("Name").fill("sanitytest");
|
||||
await page.locator('[data-test="logs-vrl-function-editor"]').click();
|
||||
await page.locator('[data-test="logs-vrl-function-editor"]').getByLabel("Editor content;Press Alt+F1").fill("sanity=1");
|
||||
await page.locator('[data-test="logs-vrl-function-editor"]').locator('.inputarea').fill("sanity=1");
|
||||
await page.locator('[data-test="logs-vrl-function-editor"]').getByText("sanity=").click();
|
||||
await page.locator('[data-test="logs-vrl-function-editor"]').getByLabel("Editor content;Press Alt+F1").press("ArrowLeft");
|
||||
await page.locator('[data-test="logs-vrl-function-editor"]').getByLabel("Editor content;Press Alt+F1").press("ArrowLeft");
|
||||
await page.locator('[data-test="logs-vrl-function-editor"]').getByLabel("Editor content;Press Alt+F1").press("ArrowLeft");
|
||||
await page.locator('[data-test="logs-vrl-function-editor"]').getByLabel("Editor content;Press Alt+F1").press("ArrowLeft");
|
||||
await page.locator('[data-test="logs-vrl-function-editor"]').getByLabel("Editor content;Press Alt+F1").fill(".sanity=1");
|
||||
await page.locator('[data-test="logs-vrl-function-editor"]').locator('.inputarea').press("ArrowLeft");
|
||||
await page.locator('[data-test="logs-vrl-function-editor"]').locator('.inputarea').press("ArrowLeft");
|
||||
await page.locator('[data-test="logs-vrl-function-editor"]').locator('.inputarea').press("ArrowLeft");
|
||||
await page.locator('[data-test="logs-vrl-function-editor"]').locator('.inputarea').press("ArrowLeft");
|
||||
await page.locator('[data-test="logs-vrl-function-editor"]').locator('.inputarea').fill(".sanity=1");
|
||||
await page.getByRole("button", { name: "Save" }).click();
|
||||
await page.getByPlaceholder("Search Function").click();
|
||||
await page.getByPlaceholder("Search Function").fill("sanity");
|
||||
|
||||
Generated
+2914
-2804
File diff suppressed because it is too large
Load Diff
+5
-5
@@ -79,6 +79,7 @@
|
||||
"@types/axios": "^0.14.4",
|
||||
"@types/d3-scale": "^4.0.8",
|
||||
"@types/dompurify": "^3.2.0",
|
||||
"@types/fs-extra": "^11.0.4",
|
||||
"@types/js-cookie": "^3.0.6",
|
||||
"@types/jsdom": "^21.1.7",
|
||||
"@types/leaflet": "^1.9.16",
|
||||
@@ -88,7 +89,7 @@
|
||||
"@types/uuid": "^10.0.0",
|
||||
"@vitejs/plugin-vue": "^5.2.1",
|
||||
"@vitejs/plugin-vue-jsx": "^4.1.1",
|
||||
"@vitest/coverage-v8": "^3.0.5",
|
||||
"@vitest/coverage-v8": "^3.1.1",
|
||||
"@vitest/ui": "^3.0.5",
|
||||
"@vue/eslint-config-prettier": "^10.2.0",
|
||||
"@vue/eslint-config-typescript": "^14.3.0",
|
||||
@@ -106,7 +107,7 @@
|
||||
"fs-extra": "^11.3.0",
|
||||
"happy-dom": "^16.7.2",
|
||||
"jsdom": "^26.0.0",
|
||||
"msw": "^2.7.0",
|
||||
"msw": "^2.7.3",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"postcss": "^8.4.39",
|
||||
"prettier": "^3.4.2",
|
||||
@@ -120,9 +121,8 @@
|
||||
"vite": "^6.3.4",
|
||||
"vite-plugin-istanbul": "^6.0.2",
|
||||
"vite-plugin-monaco-editor": "^1.1.0",
|
||||
"vitest": "^3.0.5",
|
||||
"vitest": "^3.1.1",
|
||||
"vitest-canvas-mock": "^0.3.3",
|
||||
"vue-tsc": "^2.2.0",
|
||||
"whatwg-fetch": "^3.6.20"
|
||||
"vue-tsc": "^2.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
+18
-3
@@ -1,8 +1,23 @@
|
||||
// Copyright 2023 OpenObserve Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { DOMWrapper, flushPromises, mount } from "@vue/test-utils";
|
||||
import { describe, expect, it, beforeEach } from "vitest";
|
||||
import { installQuasar } from "../helpers/install-quasar-plugin";
|
||||
import ConfirmDialog from "../../../components/ConfirmDialog.vue";
|
||||
import i18n from "../../../locales";
|
||||
import { installQuasar } from "@/test/unit/helpers/install-quasar-plugin";
|
||||
import ConfirmDialog from "@/components/ConfirmDialog.vue";
|
||||
import i18n from "@/locales";
|
||||
import { Dialog } from "quasar";
|
||||
|
||||
installQuasar({
|
||||
+17
-2
@@ -1,7 +1,22 @@
|
||||
// Copyright 2023 OpenObserve Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { mount } from "@vue/test-utils";
|
||||
import { describe, expect, it, beforeEach, afterEach, vi } from "vitest";
|
||||
import { installQuasar } from "../helpers/install-quasar-plugin";
|
||||
import HighLight from "../../../components/HighLight.vue";
|
||||
import { installQuasar } from "@/test/unit/helpers/install-quasar-plugin";
|
||||
import HighLight from "@/components/HighLight.vue";
|
||||
|
||||
installQuasar();
|
||||
|
||||
+19
-4
@@ -1,9 +1,24 @@
|
||||
// Copyright 2023 OpenObserve Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { mount } from "@vue/test-utils";
|
||||
import { describe, expect, it, beforeEach, afterEach, vi } from "vitest";
|
||||
import { installQuasar } from "../helpers/install-quasar-plugin";
|
||||
import MenuLink from "../../../components/MenuLink.vue";
|
||||
import i18n from "../../../locales";
|
||||
import store from "../helpers/store";
|
||||
import { installQuasar } from "@/test/unit/helpers/install-quasar-plugin";
|
||||
import MenuLink from "@/components/MenuLink.vue";
|
||||
import i18n from "@/locales";
|
||||
import store from "@/test/unit/helpers/store";
|
||||
|
||||
installQuasar();
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -53,7 +53,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
>
|
||||
<div class="row justify-start items-start" style="width: 1024px">
|
||||
<div style="width: calc(100% - 401px)">
|
||||
<q-form class="add-alert-form" ref="addAlertForm" @submit="onSubmit">
|
||||
<q-form
|
||||
class="add-alert-form"
|
||||
data-test="add-alert-form"
|
||||
ref="addAlertForm"
|
||||
@submit="onSubmit"
|
||||
>
|
||||
<div
|
||||
class="flex justify-start items-center q-pb-sm q-col-gutter-md flex-wrap"
|
||||
>
|
||||
@@ -1548,7 +1553,7 @@ export default defineComponent({
|
||||
);
|
||||
callAlert
|
||||
.then((res: { data: any }) => {
|
||||
this.formData = { ...defaultValue };
|
||||
this.formData = { ...defaultValue() };
|
||||
this.$emit("update:list", this.activeFolderId);
|
||||
this.addAlertForm.resetValidation();
|
||||
dismiss();
|
||||
|
||||
+3
-3
@@ -15,15 +15,15 @@
|
||||
|
||||
import { describe, expect, it, beforeEach, vi, afterEach } from "vitest";
|
||||
import { mount, flushPromises, DOMWrapper } from "@vue/test-utils";
|
||||
import { installQuasar } from "../../helpers/install-quasar-plugin";
|
||||
import { installQuasar } from "@/test/unit/helpers/install-quasar-plugin";
|
||||
import { Dialog, Notify } from "quasar";
|
||||
import i18n from "@/locales";
|
||||
import store from "../../helpers/store";
|
||||
import store from "@/test/unit/helpers/store";
|
||||
import DestinationService from "@/services/alert_destination";
|
||||
// @ts-ignore
|
||||
import { rest } from "msw";
|
||||
import { AddDestination } from "@/components/alerts";
|
||||
import router from "../../helpers/router";
|
||||
import router from "@/test/unit/helpers/router";
|
||||
|
||||
installQuasar({
|
||||
plugins: [Dialog, Notify],
|
||||
+3
-3
@@ -15,15 +15,15 @@
|
||||
|
||||
import { describe, expect, it, beforeEach, vi, afterEach } from "vitest";
|
||||
import { mount, flushPromises, DOMWrapper } from "@vue/test-utils";
|
||||
import { installQuasar } from "../../helpers/install-quasar-plugin";
|
||||
import { installQuasar } from "@/test/unit/helpers/install-quasar-plugin";
|
||||
import { Dialog, Notify } from "quasar";
|
||||
import i18n from "@/locales";
|
||||
import store from "../../helpers/store";
|
||||
import store from "@/test/unit/helpers/store";
|
||||
import TemplateService from "@/services/alert_templates";
|
||||
// @ts-ignore
|
||||
import { rest } from "msw";
|
||||
import { AddTemplate } from "@/components/alerts";
|
||||
import router from "../../helpers/router";
|
||||
import router from "@/test/unit/helpers/router";
|
||||
|
||||
installQuasar({
|
||||
plugins: [Dialog, Notify],
|
||||
+3
-3
@@ -15,15 +15,15 @@
|
||||
|
||||
import { describe, expect, it, beforeEach, vi, afterEach } from "vitest";
|
||||
import { mount, flushPromises, DOMWrapper } from "@vue/test-utils";
|
||||
import { installQuasar } from "../../helpers/install-quasar-plugin";
|
||||
import { installQuasar } from "@/test/unit/helpers/install-quasar-plugin";
|
||||
import { Dialog, Notify } from "quasar";
|
||||
import AlertList from "@/components/alerts/AlertList.vue";
|
||||
import i18n from "@/locales";
|
||||
import store from "../../helpers/store";
|
||||
import store from "@/test/unit/helpers/store";
|
||||
// @ts-ignore
|
||||
import { rest } from "msw";
|
||||
import AlertService from "@/services/alerts";
|
||||
import router from "../../helpers/router";
|
||||
import router from "@/test/unit/helpers/router";
|
||||
|
||||
const node = document.createElement("div");
|
||||
node.setAttribute("id", "app");
|
||||
+3
-3
@@ -15,16 +15,16 @@
|
||||
|
||||
import { describe, expect, it, beforeEach, vi, afterEach } from "vitest";
|
||||
import { mount, flushPromises, DOMWrapper } from "@vue/test-utils";
|
||||
import { installQuasar } from "../../helpers/install-quasar-plugin";
|
||||
import { installQuasar } from "@/test/unit/helpers/install-quasar-plugin";
|
||||
import { Dialog, Notify } from "quasar";
|
||||
import DestinationList from "@/components/alerts/AlertsDestinationList.vue";
|
||||
import i18n from "@/locales";
|
||||
import store from "../../helpers/store";
|
||||
import store from "@/test/unit/helpers/store";
|
||||
// @ts-ignore
|
||||
import { rest } from "msw";
|
||||
import destinationService from "@/services/alert_destination";
|
||||
|
||||
import router from "../../helpers/router";
|
||||
import router from "@/test/unit/helpers/router";
|
||||
|
||||
const node = document.createElement("div");
|
||||
node.setAttribute("id", "app");
|
||||
+16
-20
@@ -15,15 +15,14 @@
|
||||
|
||||
import { describe, expect, it, beforeEach, vi, afterEach } from "vitest";
|
||||
import { mount, flushPromises, DOMWrapper } from "@vue/test-utils";
|
||||
import { installQuasar } from "../../helpers/install-quasar-plugin";
|
||||
import { Dialog, Notify } from "quasar";
|
||||
import TemplateList from "@/components/alerts/TemplateList.vue";
|
||||
import i18n from "@/locales";
|
||||
import store from "../../helpers/store";
|
||||
// @ts-ignore
|
||||
import { rest } from "msw";
|
||||
import TemplateList from "./TemplateList.vue";
|
||||
import { http, HttpResponse } from "msw";
|
||||
import templateService from "@/services/alert_templates";
|
||||
import router from "../../helpers/router";
|
||||
import router from "@/test/unit/helpers/router";
|
||||
import { installQuasar } from "@/test/unit/helpers/install-quasar-plugin";
|
||||
import store from "@/test/unit/helpers/store";
|
||||
import i18n from "@/locales";
|
||||
|
||||
const node = document.createElement("div");
|
||||
node.setAttribute("id", "app");
|
||||
@@ -103,7 +102,7 @@ describe("Alert List", async () => {
|
||||
name: "alertTemplates",
|
||||
query: {
|
||||
action: "add",
|
||||
org_identifier: "default_organization_01",
|
||||
org_identifier: store.state.selectedOrganization.identifier,
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -113,29 +112,26 @@ describe("Alert List", async () => {
|
||||
const deleteAlert = vi.spyOn(templateService, "delete");
|
||||
beforeEach(async () => {
|
||||
global.server.use(
|
||||
rest.delete(
|
||||
http.delete(
|
||||
`${store.state.API_ENDPOINT}/api/${store.state.selectedOrganization.identifier}/alerts/templates/${template_name}`,
|
||||
(req: any, res: any, ctx: any) => {
|
||||
return res(ctx.status(200), ctx.json({ code: 200 }));
|
||||
() => {
|
||||
return HttpResponse.json({ code: 200 });
|
||||
}
|
||||
)
|
||||
);
|
||||
global.server.use(
|
||||
rest.get(
|
||||
http.get(
|
||||
`${store.state.API_ENDPOINT}/api/${store.state.selectedOrganization.identifier}/templates`,
|
||||
(req: any, res: any, ctx: any) => {
|
||||
return res(
|
||||
ctx.status(200),
|
||||
ctx.json({
|
||||
list: [
|
||||
{
|
||||
() => {
|
||||
return HttpResponse.json({
|
||||
list: [
|
||||
{
|
||||
name: "Template3",
|
||||
body: '\r\n[\r\n {\r\n "labels": {\r\n "alertname": "{alert_name}",\r\n "stream": "{stream_name}",\r\n "organization": "{org_name}",\r\n "alerttype": "{alert_type}",\r\n "severity": "critical"\r\n },\r\n "annotations": {\r\n "timestamp": "{timestamp}"\r\n }\r\n }\r\n]',
|
||||
isDefault: true,
|
||||
},
|
||||
],
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
)
|
||||
);
|
||||
@@ -16,7 +16,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
<template>
|
||||
<q-page class="q-pa-none" style="min-height: inherit">
|
||||
<div v-if=" !showImportTemplate && !showTemplateEditor">
|
||||
<div v-if="!showImportTemplate && !showTemplateEditor">
|
||||
<q-table
|
||||
data-test="alert-templates-list-table"
|
||||
ref="q-table"
|
||||
@@ -118,14 +118,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
/>
|
||||
</div>
|
||||
<div v-else>
|
||||
<ImportTemplate
|
||||
:templates="templates"
|
||||
@update:templates="getTemplates"
|
||||
/>
|
||||
<ImportTemplate :templates="templates" @update:templates="getTemplates" />
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<ConfirmDialog
|
||||
title="Delete Template"
|
||||
message="Are you sure you want to delete template?"
|
||||
@@ -150,7 +145,7 @@ import { outlinedDelete } from "@quasar/extras/material-icons-outlined";
|
||||
import ImportTemplate from "./ImportTemplate.vue";
|
||||
|
||||
const AddTemplate = defineAsyncComponent(
|
||||
() => import("@/components/alerts/AddTemplate.vue")
|
||||
() => import("@/components/alerts/AddTemplate.vue"),
|
||||
);
|
||||
|
||||
const store = useStore();
|
||||
@@ -203,11 +198,11 @@ onMounted(() => {
|
||||
watch(
|
||||
() => router.currentRoute.value.query.action,
|
||||
(action) => {
|
||||
if (!action){
|
||||
if (!action) {
|
||||
showTemplateEditor.value = false;
|
||||
showImportTemplate.value = false;
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
const getTemplates = () => {
|
||||
@@ -215,6 +210,7 @@ const getTemplates = () => {
|
||||
spinner: true,
|
||||
message: "Please wait while loading templates...",
|
||||
});
|
||||
|
||||
templateService
|
||||
.list({
|
||||
org_identifier: store.state.selectedOrganization.identifier,
|
||||
@@ -228,7 +224,7 @@ const getTemplates = () => {
|
||||
})
|
||||
.catch((err) => {
|
||||
dismiss();
|
||||
if(err.response.status != 403){
|
||||
if (err.response.status !== 403) {
|
||||
q.notify({
|
||||
type: "negative",
|
||||
message: "Error while pulling templates.",
|
||||
@@ -244,10 +240,10 @@ const updateRoute = () => {
|
||||
if (router.currentRoute.value.query.action === "add") editTemplate();
|
||||
if (router.currentRoute.value.query.action === "update")
|
||||
editTemplate(
|
||||
getTemplateByName(router.currentRoute.value.query.name as string)
|
||||
getTemplateByName(router.currentRoute.value.query.name as string),
|
||||
);
|
||||
if(router.currentRoute.value.query.action === "import") {
|
||||
showImportTemplate.value = true
|
||||
if (router.currentRoute.value.query.action === "import") {
|
||||
showImportTemplate.value = true;
|
||||
}
|
||||
};
|
||||
const getTemplateByName = (name: string) => {
|
||||
@@ -317,13 +313,13 @@ const deleteTemplate = () => {
|
||||
const importTemplate = () => {
|
||||
showImportTemplate.value = true;
|
||||
router.push({
|
||||
name: "alertTemplates",
|
||||
query: {
|
||||
action: "import",
|
||||
org_identifier: store.state.selectedOrganization.identifier,
|
||||
},
|
||||
});
|
||||
}
|
||||
name: "alertTemplates",
|
||||
query: {
|
||||
action: "import",
|
||||
org_identifier: store.state.selectedOrganization.identifier,
|
||||
},
|
||||
});
|
||||
};
|
||||
const conformDeleteDestination = (destination: any) => {
|
||||
confirmDelete.value.visible = true;
|
||||
confirmDelete.value.data = destination;
|
||||
@@ -354,24 +350,23 @@ const filterData = (rows: any, terms: any) => {
|
||||
};
|
||||
const exportTemplate = (row: any) => {
|
||||
const findTemplate: any = getTemplateByName(row.name);
|
||||
const templateByName = {...findTemplate}
|
||||
if(templateByName.hasOwnProperty("#")) delete templateByName["#"];
|
||||
const templateJson = JSON.stringify(templateByName,null,2);
|
||||
const blob = new Blob([templateJson], { type: 'application/json' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
// Create an anchor element to trigger the download
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
const templateByName = { ...findTemplate };
|
||||
if (templateByName.hasOwnProperty("#")) delete templateByName["#"];
|
||||
const templateJson = JSON.stringify(templateByName, null, 2);
|
||||
const blob = new Blob([templateJson], { type: "application/json" });
|
||||
const url = URL.createObjectURL(blob);
|
||||
// Create an anchor element to trigger the download
|
||||
const link = document.createElement("a");
|
||||
link.href = url;
|
||||
|
||||
// Set the filename of the download
|
||||
link.download = `${templateByName.name}.json`;
|
||||
// Set the filename of the download
|
||||
link.download = `${templateByName.name}.json`;
|
||||
|
||||
// Trigger the download by simulating a click
|
||||
link.click();
|
||||
// Trigger the download by simulating a click
|
||||
link.click();
|
||||
|
||||
// Clean up the URL object after download
|
||||
URL.revokeObjectURL(url);
|
||||
|
||||
}
|
||||
// Clean up the URL object after download
|
||||
URL.revokeObjectURL(url);
|
||||
};
|
||||
</script>
|
||||
<style lang=""></style>
|
||||
|
||||
@@ -36,6 +36,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
<template v-slot:body-cell-actions="props">
|
||||
<q-td :props="props">
|
||||
<q-btn
|
||||
:data-test="`${props.row.name}-explore-btn`"
|
||||
icon="search"
|
||||
:title="t('logStream.explore')"
|
||||
class="q-ml-xs"
|
||||
|
||||
+17
-2
@@ -1,12 +1,27 @@
|
||||
// Copyright 2023 OpenObserve Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import { mount } from "@vue/test-utils";
|
||||
import { installQuasar } from "../../helpers/install-quasar-plugin";
|
||||
import { installQuasar } from "@/test/unit/helpers/install-quasar-plugin";
|
||||
import { createStore } from "vuex";
|
||||
import Curl from "@/components/ingestion/logs/Curl.vue";
|
||||
|
||||
installQuasar();
|
||||
const store = createStore({
|
||||
state: {
|
||||
state: {
|
||||
organizationPasscode: 11,
|
||||
API_ENDPOINT: "http://localhost:8080",
|
||||
},
|
||||
+16
-1
@@ -1,6 +1,21 @@
|
||||
// Copyright 2023 OpenObserve Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { describe, expect, it, beforeEach } from "vitest";
|
||||
import { flushPromises, mount } from "@vue/test-utils";
|
||||
import { installQuasar } from "../../helpers/install-quasar-plugin";
|
||||
import { installQuasar } from "@/test/unit/helpers/install-quasar-plugin";
|
||||
import { createStore } from "vuex";
|
||||
import FluentBit from "@/components/ingestion/logs/FluentBit.vue";
|
||||
|
||||
+16
-1
@@ -1,6 +1,21 @@
|
||||
// Copyright 2023 OpenObserve Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { describe, expect, it, beforeEach } from "vitest";
|
||||
import { mount } from "@vue/test-utils";
|
||||
import { installQuasar } from "../../helpers/install-quasar-plugin";
|
||||
import { installQuasar } from "@/test/unit/helpers/install-quasar-plugin";
|
||||
import { createStore } from "vuex";
|
||||
import Fluentd from "@/components/ingestion/logs/Fluentd.vue";
|
||||
|
||||
+16
-1
@@ -1,6 +1,21 @@
|
||||
// Copyright 2023 OpenObserve Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { describe, expect, it, beforeEach } from "vitest";
|
||||
import { mount } from "@vue/test-utils";
|
||||
import { installQuasar } from "../../helpers/install-quasar-plugin";
|
||||
import { installQuasar } from "@/test/unit/helpers/install-quasar-plugin";
|
||||
import { createStore } from "vuex";
|
||||
import Vector from "@/components/ingestion/logs/Vector.vue";
|
||||
|
||||
@@ -0,0 +1,787 @@
|
||||
// Copyright 2023 OpenObserve Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { describe, expect, it, beforeEach, vi, afterEach } from "vitest";
|
||||
import { mount, flushPromises } from "@vue/test-utils";
|
||||
import { installQuasar } from "@/test/unit/helpers/install-quasar-plugin";
|
||||
import { Dialog, Notify } from "quasar";
|
||||
import LogStream from "@/components/logstream/schema.vue";
|
||||
import i18n from "@/locales";
|
||||
// @ts-ignore
|
||||
import store from "@/test/unit/helpers/store";
|
||||
import StreamService from "@/services/stream";
|
||||
|
||||
installQuasar({
|
||||
plugins: [Dialog, Notify],
|
||||
});
|
||||
|
||||
describe("Streams", async () => {
|
||||
let wrapper: any;
|
||||
|
||||
beforeEach(async () => {
|
||||
vi.useFakeTimers();
|
||||
const updateStream = vi.spyOn(StreamService, "updateSettings");
|
||||
|
||||
wrapper = mount(LogStream, {
|
||||
props: {
|
||||
modelValue: {
|
||||
name: "k8s_json",
|
||||
storage_type: "s3",
|
||||
stream_type: "logs",
|
||||
stats: {
|
||||
doc_time_min: 1678448628630259,
|
||||
doc_time_max: 1678448628652947,
|
||||
doc_num: 400,
|
||||
file_num: 1,
|
||||
storage_size: 0.74,
|
||||
compressed_size: 0.03,
|
||||
},
|
||||
schema: [
|
||||
{
|
||||
name: "_timestamp",
|
||||
type: "Int64",
|
||||
},
|
||||
{
|
||||
name: "kubernetes.container_hash",
|
||||
type: "Utf8",
|
||||
},
|
||||
{
|
||||
name: "log",
|
||||
type: "Utf8",
|
||||
},
|
||||
{
|
||||
name: "message",
|
||||
type: "Utf8",
|
||||
},
|
||||
{
|
||||
name: "test_this_field",
|
||||
type: "Utf8",
|
||||
},
|
||||
],
|
||||
settings: {
|
||||
partition_time_level: "hourly",
|
||||
partition_keys: {},
|
||||
full_text_search_keys: ["level", "log"],
|
||||
index_fields: [],
|
||||
bloom_filter_fields: [],
|
||||
distinct_value_fields: [],
|
||||
data_retention: 3650,
|
||||
max_query_range: 0,
|
||||
store_original_data: false,
|
||||
approx_partition: false,
|
||||
index_updated_at: 1737970280285469,
|
||||
extended_retention_days: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
global: {
|
||||
provide: {
|
||||
store: store,
|
||||
},
|
||||
plugins: [i18n],
|
||||
},
|
||||
});
|
||||
await flushPromises();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.unmount();
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it("should display title", () => {
|
||||
const pageTitle = wrapper.find('[data-test="schema-title-text"]');
|
||||
expect(pageTitle.text()).toBe("Stream Detail");
|
||||
});
|
||||
|
||||
it("Should display stream title", () => {
|
||||
const streamTitle = wrapper.find('[data-test="schema-stream-title-text"]');
|
||||
expect(streamTitle.text()).toBe("Stream Name k8s_json");
|
||||
});
|
||||
|
||||
it("Should have cancel button", () => {
|
||||
const cancelButton = wrapper.find('[data-test="schema-cancel-button"]');
|
||||
expect(cancelButton.exists()).toBeTruthy();
|
||||
expect(cancelButton.text()).toBe("Cancel");
|
||||
});
|
||||
|
||||
it("Should have Update Settings button", () => {
|
||||
const updateSettingsButton = wrapper.find(
|
||||
'[data-test="schema-update-settings-button"]',
|
||||
);
|
||||
expect(updateSettingsButton.exists()).toBeTruthy();
|
||||
expect(updateSettingsButton.text()).toBe("Update Settings");
|
||||
});
|
||||
|
||||
it("Should display stream fields mapping table", async () => {
|
||||
const table = await wrapper.find(
|
||||
'[data-test="schema-log-stream-field-mapping-table"]',
|
||||
);
|
||||
expect(table.exists()).toBeTruthy();
|
||||
});
|
||||
|
||||
it("Should display stream fields mapping title", () => {
|
||||
const table = wrapper.find(
|
||||
'[data-test="schema-log-stream-mapping-title-text"]',
|
||||
);
|
||||
expect(table.text()).toBe(
|
||||
"Mapping Default FTS keys used (no custom keys set).Store Original Data",
|
||||
);
|
||||
});
|
||||
|
||||
it("Should display stream fields mapping table headers", () => {
|
||||
const tableHeaders = wrapper
|
||||
.find('[data-test="schema-log-stream-field-mapping-table"]')
|
||||
.find("thead")
|
||||
.find("tr")
|
||||
.findAll("th");
|
||||
|
||||
expect(tableHeaders[0].text()).toBe("");
|
||||
expect(tableHeaders[1].text()).toBe("Fieldarrow_upward");
|
||||
});
|
||||
|
||||
it.skip("Should display stream fields mapping table data", () => {
|
||||
const tableData = wrapper
|
||||
.find('[data-test="schema-log-stream-field-mapping-table"]')
|
||||
.find("tbody")
|
||||
.findAll("tr")[0]
|
||||
.findAll("td");
|
||||
|
||||
expect(tableData[0].text()).toBe("");
|
||||
expect(tableData[1].text()).toBe("_timestamp");
|
||||
expect(tableData[2].text()).toBe("Int64");
|
||||
});
|
||||
|
||||
// TODO : Check if we can update this test case
|
||||
// - expect(logCheckbox.find(".q-checkbox__inner--truthy").exists()).toBeTruthy();
|
||||
// + expect(wrapper.vm.ftsKeys.includes('log')).toBeTruthy();
|
||||
|
||||
describe("When user make changes and update settings", () => {
|
||||
const updateStream = vi.spyOn(StreamService, "updateSettings");
|
||||
|
||||
vi.useFakeTimers();
|
||||
|
||||
let logPartition, timeStampCheckbox, updateSettingsButton: any;
|
||||
beforeEach(async () => {
|
||||
});
|
||||
it("Should make api call when user updates the form and click update settings ", async () => {
|
||||
// Find the q-toggle component wrapper
|
||||
const toggleWrapper = await wrapper.find(
|
||||
'[data-test="log-stream-store-original-data-toggle-btn"]',
|
||||
);
|
||||
|
||||
// Verify initial state of the toggle
|
||||
const checkBox = await toggleWrapper.find('input[type="checkbox"]');
|
||||
expect(checkBox.element.checked).toBe(false);
|
||||
|
||||
// Simulate a click on the toggle
|
||||
await checkBox.trigger("click");
|
||||
await wrapper.vm.$nextTick();
|
||||
await flushPromises();
|
||||
|
||||
await checkBox.setValue(true);
|
||||
expect(checkBox.element.checked).toBe(true);
|
||||
|
||||
// Verify that formDirtyFlag has been updated
|
||||
expect(wrapper.vm.formDirtyFlag).toBe(true);
|
||||
|
||||
// Find and trigger the update settings button
|
||||
const updateSettingsButton = wrapper.find(
|
||||
'[data-test="schema-update-settings-button"]',
|
||||
);
|
||||
expect(updateSettingsButton.attributes("disabled")).toBe(undefined); // Ensure it's enabled
|
||||
await updateSettingsButton.trigger("submit");
|
||||
|
||||
// Simulate form submission
|
||||
// const settingsForm = wrapper.find('[data-test="settings-form"]');
|
||||
// await settingsForm.trigger("submit");
|
||||
await flushPromises();
|
||||
await vi.advanceTimersByTime(500);
|
||||
await flushPromises();
|
||||
|
||||
// Verify that the API call was made (mocked in your setup)
|
||||
expect(updateStream).toHaveBeenCalledTimes(1); // Uncomment if you have a mocked function
|
||||
});
|
||||
it("Should prevent multiple API calls on rapid form submissions", async () => {
|
||||
// Simulate form changes
|
||||
const toggleWrapper = wrapper.find(
|
||||
'[data-test="log-stream-store-original-data-toggle-btn"]',
|
||||
);
|
||||
const checkBox = toggleWrapper.find('input[type="checkbox"]');
|
||||
await checkBox.setValue(true);
|
||||
await checkBox.trigger("click");
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
await checkBox.setValue(true);
|
||||
expect(checkBox.element.checked).toBe(true);
|
||||
|
||||
const updateSettingsButton = wrapper.find(
|
||||
'[data-test="schema-update-settings-button"]',
|
||||
);
|
||||
|
||||
// Rapidly trigger multiple submissions
|
||||
await Promise.all([
|
||||
updateSettingsButton.trigger("submit"),
|
||||
updateSettingsButton.trigger("submit"),
|
||||
updateSettingsButton.trigger("submit"),
|
||||
]);
|
||||
|
||||
await flushPromises();
|
||||
|
||||
// Verify that only one API call was made
|
||||
expect(updateStream).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
it("Should not call update settings API if retention days is less than 1", async () => {
|
||||
// Simulate form changes
|
||||
const retentionDaysInput = await wrapper.find(
|
||||
'[data-test="stream-details-data-retention-input"]',
|
||||
);
|
||||
|
||||
await retentionDaysInput.setValue(0); // Set retention days to less than 1
|
||||
await retentionDaysInput.trigger("input");
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
// Verify that formDirtyFlag has been updated
|
||||
expect(wrapper.vm.formDirtyFlag).toBe(true);
|
||||
|
||||
// Find and trigger the update settings button
|
||||
const updateSettingsButton = wrapper.find(
|
||||
'[data-test="schema-update-settings-button"]',
|
||||
);
|
||||
expect(updateSettingsButton.attributes("disabled")).toBe(undefined); // Ensure it's enabled
|
||||
await updateSettingsButton.trigger("submit");
|
||||
|
||||
await flushPromises();
|
||||
await vi.advanceTimersByTime(500);
|
||||
await flushPromises();
|
||||
|
||||
// Verify that the API call was not made
|
||||
expect(updateStream).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
it("Should handle API error when updating settings", async () => {
|
||||
// Mock the API to return an error
|
||||
await flushPromises();
|
||||
|
||||
// Simulate form changes
|
||||
const toggleWrapper = wrapper.find(
|
||||
'[data-test="log-stream-store-original-data-toggle-btn"]',
|
||||
);
|
||||
const checkBox = toggleWrapper.find('input[type="checkbox"]');
|
||||
await checkBox.setValue(true);
|
||||
await checkBox.trigger("click");
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
await checkBox.setValue(true);
|
||||
expect(checkBox.element.checked).toBe(true);
|
||||
|
||||
// Verify that formDirtyFlag has been updated
|
||||
expect(wrapper.vm.formDirtyFlag).toBe(true);
|
||||
|
||||
// Find and trigger the update settings button
|
||||
const updateSettingsButton = wrapper.find(
|
||||
'[data-test="schema-update-settings-button"]',
|
||||
);
|
||||
expect(updateSettingsButton.attributes("disabled")).toBe(undefined); // Ensure it's enabled
|
||||
await updateSettingsButton.trigger("submit");
|
||||
|
||||
await flushPromises();
|
||||
await vi.advanceTimersByTime(500);
|
||||
await flushPromises();
|
||||
|
||||
// Verify that the API call was made and handled the error
|
||||
expect(updateStream).toHaveBeenCalledTimes(1);
|
||||
expect(
|
||||
updateStream.mock.settledResults[0].value.response.data.message,
|
||||
).toBe("Internal Server Error"); // Assuming you set an errorMessage in your component
|
||||
});
|
||||
it("Should update index type to prefixPartition when selected and verify using update call", async () => {
|
||||
await flushPromises();
|
||||
// Find the index type select dropdown within the table row
|
||||
const indexTypeSelectWrapper = wrapper
|
||||
.find('[data-test="schema-log-stream-field-mapping-table"]')
|
||||
.findAll("tbody tr")
|
||||
.at(1) // Assuming you want to select the first row for this test
|
||||
.find('[data-test="schema-stream-index-select"]');
|
||||
const indexTypeSelector = indexTypeSelectWrapper.findComponent({
|
||||
name: "QSelect",
|
||||
});
|
||||
|
||||
// Simulate selecting the "prefixPartition" option
|
||||
await indexTypeSelector.vm.$emit("update:modelValue", [
|
||||
"prefixPartition",
|
||||
]);
|
||||
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
// Verify that the selected value is "prefixPartition"
|
||||
// expect(indexTypeSelect.element.value).toBe("prefixPartition");
|
||||
|
||||
// Verify that formDirtyFlag has been updated
|
||||
expect(wrapper.vm.formDirtyFlag).toBe(true);
|
||||
// Find and trigger the update settings button
|
||||
const updateSettingsButton = wrapper.find(
|
||||
'[data-test="schema-update-settings-button"]',
|
||||
);
|
||||
expect(updateSettingsButton.attributes("disabled")).toBe(undefined); // Ensure it's enabled
|
||||
await updateSettingsButton.trigger("submit");
|
||||
await flushPromises();
|
||||
await vi.advanceTimersByTime(500);
|
||||
await flushPromises();
|
||||
const parsedRequest = JSON.parse(
|
||||
updateStream.mock.settledResults[0].value.config.data,
|
||||
);
|
||||
|
||||
parsedRequest.partition_keys.add.forEach((index: any) => {
|
||||
if (index.field == "kubernetes.container_hash") {
|
||||
expect(index.types).toEqual("prefix");
|
||||
}
|
||||
});
|
||||
// Verify that the API call was made
|
||||
expect(updateStream).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
it("Should update index type to fullTextSearchKey when selected and verify using update call", async () => {
|
||||
await flushPromises();
|
||||
// Find the index type select dropdown within the table row
|
||||
const indexTypeSelectWrapper = wrapper
|
||||
.find('[data-test="schema-log-stream-field-mapping-table"]')
|
||||
.findAll("tbody tr")
|
||||
.at(1) // Assuming you want to select the first row for this test
|
||||
.find('[data-test="schema-stream-index-select"]');
|
||||
const indexTypeSelector = indexTypeSelectWrapper.findComponent({
|
||||
name: "QSelect",
|
||||
});
|
||||
|
||||
// Simulate selecting the "prefixPartition" option
|
||||
await indexTypeSelector.vm.$emit("update:modelValue", [
|
||||
"fullTextSearchKey",
|
||||
]);
|
||||
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
// Verify that the selected value is "prefixPartition"
|
||||
// expect(indexTypeSelect.element.value).toBe("prefixPartition");
|
||||
|
||||
// Verify that formDirtyFlag has been updated
|
||||
expect(wrapper.vm.formDirtyFlag).toBe(true);
|
||||
// Find and trigger the update settings button
|
||||
const updateSettingsButton = wrapper.find(
|
||||
'[data-test="schema-update-settings-button"]',
|
||||
);
|
||||
expect(updateSettingsButton.attributes("disabled")).toBe(undefined); // Ensure it's enabled
|
||||
await updateSettingsButton.trigger("submit");
|
||||
await flushPromises();
|
||||
await vi.advanceTimersByTime(500);
|
||||
await flushPromises();
|
||||
const parsedRequest = JSON.parse(
|
||||
updateStream.mock.settledResults[0].value.config.data,
|
||||
);
|
||||
expect(parsedRequest.full_text_search_keys.add[0]).toEqual(
|
||||
"kubernetes.container_hash",
|
||||
);
|
||||
// Verify that the API call was made
|
||||
expect(updateStream).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
it("Should update index type to keyPartition when selected and verify using update call", async () => {
|
||||
await flushPromises();
|
||||
// Find the index type select dropdown within the table row
|
||||
const indexTypeSelectWrapper = wrapper
|
||||
.find('[data-test="schema-log-stream-field-mapping-table"]')
|
||||
.findAll("tbody tr")
|
||||
.at(2) // Assuming you want to select the first row for this test
|
||||
.find('[data-test="schema-stream-index-select"]');
|
||||
const indexTypeSelector = indexTypeSelectWrapper.findComponent({
|
||||
name: "QSelect",
|
||||
});
|
||||
|
||||
// Simulate selecting the "prefixPartition" option
|
||||
await indexTypeSelector.vm.$emit("update:modelValue", ["keyPartition"]);
|
||||
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
// Verify that the selected value is "prefixPartition"
|
||||
// expect(indexTypeSelect.element.value).toBe("prefixPartition");
|
||||
|
||||
// Verify that formDirtyFlag has been updated
|
||||
expect(wrapper.vm.formDirtyFlag).toBe(true);
|
||||
// Find and trigger the update settings button
|
||||
const updateSettingsButton = wrapper.find(
|
||||
'[data-test="schema-update-settings-button"]',
|
||||
);
|
||||
expect(updateSettingsButton.attributes("disabled")).toBe(undefined); // Ensure it's enabled
|
||||
await updateSettingsButton.trigger("submit");
|
||||
await flushPromises();
|
||||
await vi.advanceTimersByTime(500);
|
||||
await flushPromises();
|
||||
const parsedRequest = JSON.parse(
|
||||
updateStream.mock.settledResults[0].value.config.data,
|
||||
);
|
||||
|
||||
parsedRequest.partition_keys.add.forEach((index: any) => {
|
||||
if (index.field == "log") {
|
||||
expect(index.types).toEqual("value");
|
||||
}
|
||||
});
|
||||
// Verify that the API call was made
|
||||
expect(updateStream).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
it("Should update index type to hashPartition_8 when selected and verify using update call", async () => {
|
||||
await flushPromises();
|
||||
// Find the index type select dropdown within the table row
|
||||
const indexTypeSelectWrapper = wrapper
|
||||
.find('[data-test="schema-log-stream-field-mapping-table"]')
|
||||
.findAll("tbody tr")
|
||||
.at(3) // Assuming you want to select the first row for this test
|
||||
.find('[data-test="schema-stream-index-select"]');
|
||||
const indexTypeSelector = indexTypeSelectWrapper.findComponent({
|
||||
name: "QSelect",
|
||||
});
|
||||
|
||||
// Simulate selecting the "prefixPartition" option
|
||||
await indexTypeSelector.vm.$emit("update:modelValue", [
|
||||
"hashPartition_8",
|
||||
]);
|
||||
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
// Verify that the selected value is "prefixPartition"
|
||||
// expect(indexTypeSelect.element.value).toBe("prefixPartition");
|
||||
|
||||
// Verify that formDirtyFlag has been updated
|
||||
expect(wrapper.vm.formDirtyFlag).toBe(true);
|
||||
// Find and trigger the update settings button
|
||||
const updateSettingsButton = wrapper.find(
|
||||
'[data-test="schema-update-settings-button"]',
|
||||
);
|
||||
expect(updateSettingsButton.attributes("disabled")).toBe(undefined); // Ensure it's enabled
|
||||
await updateSettingsButton.trigger("submit");
|
||||
await flushPromises();
|
||||
await vi.advanceTimersByTime(500);
|
||||
await flushPromises();
|
||||
const parsedRequest = JSON.parse(
|
||||
updateStream.mock.settledResults[0].value.config.data,
|
||||
);
|
||||
|
||||
parsedRequest.partition_keys.add.forEach((index: any) => {
|
||||
if (index.field == "message") {
|
||||
expect(index.types.hash).toEqual(8);
|
||||
}
|
||||
});
|
||||
// Verify that the API call was made
|
||||
expect(updateStream).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
it("Should add fields to user defined schema", async () => {
|
||||
await flushPromises();
|
||||
// Find the index type select dropdown within the table row
|
||||
const indexTypeSelectWrapper = wrapper.find(
|
||||
'[data-test="schema-stream-delete-log-field-fts-key-checkbox"]',
|
||||
);
|
||||
const indexTypeSelector = await indexTypeSelectWrapper.find(
|
||||
'input[type="checkbox"]',
|
||||
);
|
||||
|
||||
await indexTypeSelector.setValue(true);
|
||||
await indexTypeSelector.trigger("click");
|
||||
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
|
||||
const updateSchemaBtn = await wrapper.find(
|
||||
'[data-test="schema-add-field-button"]',
|
||||
);
|
||||
|
||||
await updateSchemaBtn.trigger("click");
|
||||
|
||||
// wrapper.vm.formDirtyFlag = true;
|
||||
|
||||
await wrapper.vm.$nextTick(); // Find and trigger the update settings button
|
||||
const updateSettingsButton = wrapper.find(
|
||||
'[data-test="schema-update-settings-button"]',
|
||||
);
|
||||
await updateSettingsButton.trigger("submit");
|
||||
await flushPromises();
|
||||
await vi.advanceTimersByTime(500);
|
||||
await flushPromises();
|
||||
const parsedRequest = JSON.parse(
|
||||
updateStream.mock.settledResults[0].value.config.data,
|
||||
);
|
||||
|
||||
parsedRequest.partition_keys.add.forEach((index: any) => {
|
||||
expect(index).toEqual("log");
|
||||
});
|
||||
// Verify that the API call was made
|
||||
expect(updateStream).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
describe("disable options test cases", () => {
|
||||
it("disable Options: should disable options correctly based on row data", async () => {
|
||||
const wrapper = mount(LogStream, {
|
||||
props: {
|
||||
modelValue: {
|
||||
name: "k8s_json",
|
||||
storage_type: "s3",
|
||||
stream_type: "logs",
|
||||
stats: {
|
||||
doc_time_min: 1678448628630259,
|
||||
doc_time_max: 1678448628652947,
|
||||
doc_num: 400,
|
||||
file_num: 1,
|
||||
storage_size: 0.74,
|
||||
compressed_size: 0.03,
|
||||
},
|
||||
schema: [
|
||||
{
|
||||
name: "_timestamp",
|
||||
type: "Int64",
|
||||
},
|
||||
{
|
||||
name: "kubernetes.container_hash",
|
||||
type: "Utf8",
|
||||
},
|
||||
{
|
||||
name: "log",
|
||||
type: "Utf8",
|
||||
},
|
||||
{
|
||||
name: "message",
|
||||
type: "Utf8",
|
||||
},
|
||||
{
|
||||
name: "test_this_field",
|
||||
type: "Utf8",
|
||||
},
|
||||
],
|
||||
settings: {
|
||||
partition_time_level: "hourly",
|
||||
partition_keys: {},
|
||||
full_text_search_keys: ["level", "log"],
|
||||
index_fields: [],
|
||||
bloom_filter_fields: [],
|
||||
distinct_value_fields: [],
|
||||
data_retention: 3650,
|
||||
max_query_range: 0,
|
||||
store_original_data: false,
|
||||
approx_partition: false,
|
||||
index_updated_at: 1737970280285469,
|
||||
extended_retention_days: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
global: {
|
||||
provide: {
|
||||
store: store,
|
||||
},
|
||||
plugins: [i18n],
|
||||
},
|
||||
});
|
||||
|
||||
const disableOptions = wrapper.vm.disableOptions;
|
||||
|
||||
const row = {
|
||||
name: "log",
|
||||
index_type: ["fullTextSearchKey"],
|
||||
};
|
||||
|
||||
const option = { value: "prefixPartition" };
|
||||
const result = disableOptions(row, option);
|
||||
expect(result).toBe(false);
|
||||
|
||||
row.index_type = ["keyPartition"];
|
||||
const result2 = disableOptions(row, option);
|
||||
expect(result2).toBe(true);
|
||||
});
|
||||
});
|
||||
describe("filterFieldFn test cases", () => {
|
||||
const rows = [
|
||||
{ name: "log" },
|
||||
{ name: "message" },
|
||||
{ name: "kubernetes.container_hash" },
|
||||
{ name: "_timestamp" },
|
||||
];
|
||||
|
||||
const indexData = {
|
||||
value: {
|
||||
defined_schema_fields: ["log", "message"],
|
||||
},
|
||||
};
|
||||
|
||||
it("should filter rows based on field name", () => {
|
||||
const filterFieldFn = wrapper.vm.filterFieldFn;
|
||||
|
||||
const terms = "log";
|
||||
const result = filterFieldFn(rows, terms);
|
||||
expect(result).toEqual([{ name: "log" }]);
|
||||
});
|
||||
|
||||
it("should filter rows based on field name and schemaFields type", () => {
|
||||
const filterFieldFn = wrapper.vm.filterFieldFn;
|
||||
|
||||
const terms = "message";
|
||||
const result = filterFieldFn(rows, terms);
|
||||
expect(result).toEqual([{ name: "message" }]);
|
||||
});
|
||||
|
||||
it("should return all rows if field is empty and type is schemaFields", () => {
|
||||
const filterFieldFn = wrapper.vm.filterFieldFn;
|
||||
|
||||
const terms = "@schemaFields";
|
||||
const result = filterFieldFn(rows, terms);
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
|
||||
it("should return all rows if field is empty", () => {
|
||||
const filterFieldFn = wrapper.vm.filterFieldFn;
|
||||
|
||||
const terms = "";
|
||||
const result = filterFieldFn(rows, terms);
|
||||
expect(result).toEqual(rows);
|
||||
});
|
||||
|
||||
it("should return empty array if no rows match the field", () => {
|
||||
const filterFieldFn = wrapper.vm.filterFieldFn;
|
||||
|
||||
const terms = "nonexistent";
|
||||
const result = filterFieldFn(rows, terms);
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
|
||||
it("should filter rows based on field name case insensitively", () => {
|
||||
const filterFieldFn = wrapper.vm.filterFieldFn;
|
||||
|
||||
const terms = "LOG";
|
||||
const result = filterFieldFn(rows, terms);
|
||||
expect(result).toEqual([{ name: "log" }]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Schema Field Management", () => {
|
||||
let wrapper: any;
|
||||
|
||||
beforeEach(async () => {
|
||||
vi.useFakeTimers();
|
||||
wrapper = mount(LogStream, {
|
||||
props: {
|
||||
modelValue: {
|
||||
name: "k8s_json",
|
||||
storage_type: "s3",
|
||||
stream_type: "logs",
|
||||
stats: {
|
||||
doc_time_min: 1678448628630259,
|
||||
doc_time_max: 1678448628652947,
|
||||
doc_num: 400,
|
||||
file_num: 1,
|
||||
storage_size: 0.74,
|
||||
compressed_size: 0.03,
|
||||
},
|
||||
schema: [
|
||||
{
|
||||
name: "_timestamp",
|
||||
type: "Int64",
|
||||
},
|
||||
{
|
||||
name: "kubernetes.container_hash",
|
||||
type: "Utf8",
|
||||
},
|
||||
{
|
||||
name: "log",
|
||||
type: "Utf8",
|
||||
},
|
||||
{
|
||||
name: "message",
|
||||
type: "Utf8",
|
||||
},
|
||||
{
|
||||
name: "test_this_field",
|
||||
type: "Utf8",
|
||||
},
|
||||
],
|
||||
settings: {
|
||||
partition_time_level: "hourly",
|
||||
partition_keys: {},
|
||||
full_text_search_keys: ["level", "log"],
|
||||
index_fields: [],
|
||||
bloom_filter_fields: [],
|
||||
distinct_value_fields: [],
|
||||
data_retention: 3650,
|
||||
max_query_range: 0,
|
||||
store_original_data: false,
|
||||
approx_partition: false,
|
||||
index_updated_at: 1737970280285469,
|
||||
extended_retention_days: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
global: {
|
||||
provide: {
|
||||
store: store,
|
||||
},
|
||||
plugins: [i18n],
|
||||
},
|
||||
});
|
||||
await flushPromises();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.unmount();
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it("should add a new schema field", async () => {
|
||||
const addSchemaFieldButton = wrapper.find(
|
||||
'[data-test="schema-add-fields-title"]',
|
||||
);
|
||||
await addSchemaFieldButton.trigger("click");
|
||||
|
||||
expect(wrapper.vm.newSchemaFields.length).toBe(1);
|
||||
expect(wrapper.vm.newSchemaFields[0]).toEqual({
|
||||
name: "",
|
||||
type: "",
|
||||
index_type: [],
|
||||
});
|
||||
expect(wrapper.vm.formDirtyFlag).toBe(true);
|
||||
});
|
||||
|
||||
it("should remove a schema field", async () => {
|
||||
const addSchemaFieldButton = wrapper.find(
|
||||
'[data-test="schema-add-fields-title"]',
|
||||
);
|
||||
await addSchemaFieldButton.trigger("click");
|
||||
wrapper.vm.newSchemaFields = [
|
||||
{ name: "field1", type: "Utf8", index_type: [] },
|
||||
{ name: "field2", type: "Int64", index_type: [] },
|
||||
];
|
||||
wrapper.vm.removeSchemaField(0);
|
||||
expect(wrapper.vm.newSchemaFields.length).toBe(1);
|
||||
expect(wrapper.vm.newSchemaFields[0]).toEqual({
|
||||
name: "field2",
|
||||
type: "Int64",
|
||||
index_type: [],
|
||||
});
|
||||
});
|
||||
|
||||
it("should close dialog and reset newSchemaFields when last field is removed", async () => {
|
||||
wrapper.vm.newSchemaFields = [
|
||||
{ name: "field1", type: "Utf8", index_type: [] },
|
||||
];
|
||||
wrapper.vm.isDialogOpen = true;
|
||||
wrapper.vm.removeSchemaField(0);
|
||||
|
||||
expect(wrapper.vm.newSchemaFields.length).toBe(0);
|
||||
expect(wrapper.vm.isDialogOpen).toBe(false);
|
||||
expect(wrapper.vm.newSchemaFields).toEqual([]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -31,8 +31,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<q-btn v-close-popup="true" round
|
||||
flat icon="close" />
|
||||
<q-btn v-close-popup="true" round flat icon="close" />
|
||||
</div>
|
||||
</div>
|
||||
</q-card-section>
|
||||
@@ -54,8 +53,7 @@ flat icon="close" />
|
||||
>
|
||||
No data available.
|
||||
</div>
|
||||
<div v-else
|
||||
class="indexDetailsContainer" style="height: 100vh">
|
||||
<div v-else class="indexDetailsContainer" style="height: 100vh">
|
||||
<div
|
||||
class="titleContainer tw-flex tw-flex-col tw-items-flex-start tw-gap-5"
|
||||
>
|
||||
@@ -65,7 +63,7 @@ class="indexDetailsContainer" style="height: 100vh">
|
||||
>
|
||||
<div data-test="schema-stream-title-text">
|
||||
{{ t("alerts.stream_name") }}
|
||||
<span class="title q-pl-xs" > {{ indexData.name }}</span>
|
||||
<span class="title q-pl-xs"> {{ indexData.name }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="store.state.zoConfig.show_stream_stats_doc_num"
|
||||
@@ -109,18 +107,15 @@ class="indexDetailsContainer" style="height: 100vh">
|
||||
v-if="store.state.zoConfig.show_stream_stats_doc_num"
|
||||
data-test="schema-stream-title-text"
|
||||
>
|
||||
|
||||
<span class="q-px-xs">
|
||||
Start Time:
|
||||
<span class="title">{{ indexData.stats.doc_time_min }}</span>
|
||||
</span>
|
||||
|
||||
<span class="q-px-xs">
|
||||
Start Time:
|
||||
<span class="title">{{ indexData.stats.doc_time_min }}</span>
|
||||
</span>
|
||||
|
||||
<span class=" q-px-xs">
|
||||
End Time:
|
||||
<span class="title">{{ indexData.stats.doc_time_max }}</span>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -197,7 +192,9 @@ class="indexDetailsContainer" style="height: 100vh">
|
||||
<q-tabs v-model="activeMainTab" inline-label dense>
|
||||
<!-- Schema Settings Tab with conditional class -->
|
||||
<q-tab
|
||||
:class="{ 'text-primary': activeMainTab === 'schemaSettings' }"
|
||||
:class="{
|
||||
'text-primary': activeMainTab === 'schemaSettings',
|
||||
}"
|
||||
name="schemaSettings"
|
||||
icon="settings"
|
||||
label="Schema Settings"
|
||||
@@ -205,13 +202,12 @@ class="indexDetailsContainer" style="height: 100vh">
|
||||
|
||||
<!-- Red Button Tab -->
|
||||
<q-tab
|
||||
:class="{ 'text-primary': activeMainTab === 'redButton' }"
|
||||
:class="{ 'text-primary': activeMainTab === 'redButton' }"
|
||||
name="redButton"
|
||||
icon="backup"
|
||||
label="Extended Retention"
|
||||
/>
|
||||
</q-tabs>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- schema settings tab -->
|
||||
@@ -301,14 +297,17 @@ class="indexDetailsContainer" style="height: 100vh">
|
||||
<div class="q-mb-md" v-if="isDialogOpen">
|
||||
<q-card class="add-fields-card">
|
||||
<!-- Header Section -->
|
||||
<q-card-section class="q-pa-none" style="padding: 8px 16px 6px 16px">
|
||||
<q-card-section
|
||||
class="q-pa-none"
|
||||
style="padding: 8px 16px 6px 16px"
|
||||
>
|
||||
<div class="tw-flex tw-justify-between tw-items-center">
|
||||
<div class="text-h6">Add Field(s)</div>
|
||||
<div>
|
||||
<q-btn
|
||||
data-test="add-stream-cancel-btn"
|
||||
icon="close"
|
||||
class=" text-bold q-mr-md"
|
||||
class="text-bold q-mr-md"
|
||||
text-color="light-text"
|
||||
no-caps
|
||||
dense
|
||||
@@ -490,27 +489,24 @@ class="indexDetailsContainer" style="height: 100vh">
|
||||
<q-icon name="info" class="q-mr-xs" size="16px" />
|
||||
|
||||
Additional
|
||||
{{ store.state.zoConfig.extended_data_retention_days }} days of extension
|
||||
will be applied to the selected date ranges</span
|
||||
{{ store.state.zoConfig.extended_data_retention_days }} days of
|
||||
extension will be applied to the selected date ranges</span
|
||||
>
|
||||
</div>
|
||||
<div class="q-mt-sm">
|
||||
<div class="text-center q-mt-sm tw-flex items-center ">
|
||||
<div class="text-center q-mt-sm tw-flex items-center">
|
||||
<div class="flex items-center">
|
||||
<span class="text-bold"> Select Date</span>
|
||||
<date-time
|
||||
class="q-mx-sm"
|
||||
@on:date-change="dateChangeValue"
|
||||
disable-relative
|
||||
hide-relative-time
|
||||
hide-relative-timezone
|
||||
:minDate="minDate"
|
||||
/>
|
||||
<date-time
|
||||
class="q-mx-sm"
|
||||
@on:date-change="dateChangeValue"
|
||||
disable-relative
|
||||
hide-relative-time
|
||||
hide-relative-timezone
|
||||
:minDate="minDate"
|
||||
/>
|
||||
</div>
|
||||
<span class="text-bold">
|
||||
(UTC Timezone)
|
||||
</span>
|
||||
|
||||
<span class="text-bold"> (UTC Timezone) </span>
|
||||
</div>
|
||||
|
||||
<div class="q-mt-sm" style="margin-bottom: 30px">
|
||||
@@ -549,7 +545,6 @@ class="indexDetailsContainer" style="height: 100vh">
|
||||
</q-td>
|
||||
</template>
|
||||
|
||||
|
||||
<template #bottom="scope">
|
||||
<QTablePagination
|
||||
:scope="scope"
|
||||
@@ -581,10 +576,7 @@ class="indexDetailsContainer" style="height: 100vh">
|
||||
selected</span
|
||||
>
|
||||
<q-btn
|
||||
v-if="
|
||||
isSchemaUDSEnabled &&
|
||||
activeMainTab == 'schemaSettings'
|
||||
"
|
||||
v-if="isSchemaUDSEnabled && activeMainTab == 'schemaSettings'"
|
||||
data-test="schema-add-field-button"
|
||||
class="q-my-sm no-border text-bold q-mr-md"
|
||||
padding="sm md"
|
||||
@@ -603,10 +595,9 @@ class="indexDetailsContainer" style="height: 100vh">
|
||||
: t("logStream.addSchemaField")
|
||||
}}
|
||||
</q-btn>
|
||||
{{ }}
|
||||
<q-btn
|
||||
v-bind:disable="
|
||||
!selectedFields.length && (!selectedDateFields.length)
|
||||
!selectedFields.length && !selectedDateFields.length
|
||||
"
|
||||
data-test="schema-delete-button"
|
||||
class="q-my-sm text-bold btn-delete"
|
||||
@@ -616,7 +607,11 @@ class="indexDetailsContainer" style="height: 100vh">
|
||||
dense
|
||||
flat
|
||||
style="border: 1px red solid"
|
||||
@click="activeMainTab == 'schemaSettings' ? confirmQueryModeChangeDialog = true : confirmDeleteDatesDialog = true"
|
||||
@click="
|
||||
activeMainTab == 'schemaSettings'
|
||||
? (confirmQueryModeChangeDialog = true)
|
||||
: (confirmDeleteDatesDialog = true)
|
||||
"
|
||||
>
|
||||
<span class="flex items-center tw-gap-1">
|
||||
<q-icon size="14px" :name="outlinedDelete" />
|
||||
@@ -769,7 +764,7 @@ export default defineComponent({
|
||||
const isDialogOpen = ref(false);
|
||||
const redDaysList = ref([]);
|
||||
const resultTotal = ref<number>(0);
|
||||
const perPageOptions : any = [
|
||||
const perPageOptions: any = [
|
||||
{ label: "5", value: 5 },
|
||||
{ label: "10", value: 10 },
|
||||
{ label: "20", value: 20 },
|
||||
@@ -997,16 +992,19 @@ export default defineComponent({
|
||||
}
|
||||
if (Array.isArray(streamResponse.settings.extended_retention_days)) {
|
||||
redBtnRows.value = [];
|
||||
indexData.value.extended_retention_days = streamResponse.settings.extended_retention_days;
|
||||
streamResponse.settings.extended_retention_days.forEach((field, index) => {
|
||||
redBtnRows.value.push({
|
||||
index: index,
|
||||
original_start: field.start,
|
||||
original_end: field.end,
|
||||
start: convertUnixToQuasarFormat(field.start),
|
||||
end: convertUnixToQuasarFormat(field.end),
|
||||
});
|
||||
});
|
||||
indexData.value.extended_retention_days =
|
||||
streamResponse.settings.extended_retention_days;
|
||||
streamResponse.settings.extended_retention_days.forEach(
|
||||
(field, index) => {
|
||||
redBtnRows.value.push({
|
||||
index: index,
|
||||
original_start: field.start,
|
||||
original_end: field.end,
|
||||
start: convertUnixToQuasarFormat(field.start),
|
||||
end: convertUnixToQuasarFormat(field.end),
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
@@ -1153,12 +1151,12 @@ export default defineComponent({
|
||||
if (selectedDateFields.value.length > 0) {
|
||||
selectedDateFields.value.forEach((field) => {
|
||||
// Filter out the items only if both start and end match
|
||||
settings.extended_retention_days = settings.extended_retention_days.filter((item) => {
|
||||
return !(item.start === field.start && item.end === field.end);
|
||||
settings.extended_retention_days =
|
||||
settings.extended_retention_days.filter((item) => {
|
||||
return !(item.start === field.start && item.end === field.end);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
let added_part_keys = [];
|
||||
for (var property of indexData.value.schema) {
|
||||
@@ -1545,44 +1543,46 @@ export default defineComponent({
|
||||
const dateToFormat = new Date(unixSeconds * 1000);
|
||||
const formattedDate = dateToFormat.toISOString();
|
||||
return date.formatDate(formattedDate, "DD-MM-YYYY");
|
||||
|
||||
}
|
||||
function formatDate(dateString) {
|
||||
const date = new Date(dateString); // Convert to Date object
|
||||
const day = String(date.getDate()).padStart(2, '0'); // Get day with leading zero
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0'); // Get month with leading zero
|
||||
const day = String(date.getDate()).padStart(2, "0"); // Get day with leading zero
|
||||
const month = String(date.getMonth() + 1).padStart(2, "0"); // Get month with leading zero
|
||||
const year = date.getFullYear(); // Get the full year
|
||||
|
||||
|
||||
return `${day}-${month}-${year}`; // Return formatted date
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const dateChangeValue = (value) => {
|
||||
|
||||
const selectedFromDate = value.hasOwnProperty('selectedDate') && formatDate(value.selectedDate.from)
|
||||
const selectedToDate =value.hasOwnProperty('selectedDate') && formatDate(value.selectedDate.to)
|
||||
const selectedFromDate =
|
||||
value.hasOwnProperty("selectedDate") &&
|
||||
formatDate(value.selectedDate.from);
|
||||
const selectedToDate =
|
||||
value.hasOwnProperty("selectedDate") &&
|
||||
formatDate(value.selectedDate.to);
|
||||
if (value.relativeTimePeriod == null) {
|
||||
try {
|
||||
const startTimestamp = convertDateToTimestamp(selectedFromDate, "00:00", 'UTC').timestamp;
|
||||
const endTimestamp = convertDateToTimestamp(selectedToDate, "00:00", 'UTC').timestamp;
|
||||
|
||||
if (startTimestamp && endTimestamp) {
|
||||
redDaysList.value.push({
|
||||
start: startTimestamp,
|
||||
end: endTimestamp,
|
||||
});
|
||||
onSubmit();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error processing date selection:', error);
|
||||
const startTimestamp = convertDateToTimestamp(
|
||||
selectedFromDate,
|
||||
"00:00",
|
||||
"UTC",
|
||||
).timestamp;
|
||||
const endTimestamp = convertDateToTimestamp(
|
||||
selectedToDate,
|
||||
"00:00",
|
||||
"UTC",
|
||||
).timestamp;
|
||||
|
||||
if (startTimestamp && endTimestamp) {
|
||||
redDaysList.value.push({
|
||||
start: startTimestamp,
|
||||
end: endTimestamp,
|
||||
});
|
||||
onSubmit();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error processing date selection:", error);
|
||||
}
|
||||
}
|
||||
};
|
||||
const calculateDateRange = () => {
|
||||
@@ -1603,7 +1603,6 @@ export default defineComponent({
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
const deleteDates = () => {
|
||||
selectedDateFields.value = selectedDateFields.value.map((field) => {
|
||||
return {
|
||||
@@ -1613,7 +1612,7 @@ export default defineComponent({
|
||||
});
|
||||
formDirtyFlag.value = true;
|
||||
onSubmit();
|
||||
};
|
||||
};
|
||||
|
||||
return {
|
||||
t,
|
||||
|
||||
@@ -339,7 +339,10 @@ export const usePanelDataLoader = (
|
||||
|
||||
state.isOperationCancelled = true;
|
||||
|
||||
if (isWebSocketEnabled() && state.searchRequestTraceIds) {
|
||||
if (
|
||||
isWebSocketEnabled(store.state) &&
|
||||
state.searchRequestTraceIds
|
||||
) {
|
||||
try {
|
||||
// loop on state.searchRequestTraceIds
|
||||
state.searchRequestTraceIds.forEach((traceId) => {
|
||||
@@ -1439,7 +1442,7 @@ export const usePanelDataLoader = (
|
||||
: [];
|
||||
state.annotations = annotations;
|
||||
|
||||
if (isStreamingEnabled()) {
|
||||
if (isStreamingEnabled(store.state)) {
|
||||
await getDataThroughStreaming(
|
||||
query,
|
||||
it,
|
||||
@@ -1449,7 +1452,7 @@ export const usePanelDataLoader = (
|
||||
panelQueryIndex,
|
||||
abortControllerRef,
|
||||
);
|
||||
} else if (isWebSocketEnabled()) {
|
||||
} else if (isWebSocketEnabled(store.state)) {
|
||||
await getDataThroughWebSocket(
|
||||
query,
|
||||
it,
|
||||
@@ -1745,7 +1748,7 @@ export const usePanelDataLoader = (
|
||||
: errorDetailValue;
|
||||
|
||||
const errorCode =
|
||||
isWebSocketEnabled() || isStreamingEnabled()
|
||||
isWebSocketEnabled(store.state) || isStreamingEnabled(store.state)
|
||||
? error?.response?.data?.code || error?.code || error?.status || ""
|
||||
: error?.response?.status ||
|
||||
error?.status ||
|
||||
@@ -2166,7 +2169,7 @@ export const usePanelDataLoader = (
|
||||
}
|
||||
|
||||
// for websocket
|
||||
if (isWebSocketEnabled() && state.searchRequestTraceIds) {
|
||||
if (isWebSocketEnabled(store.state) && state.searchRequestTraceIds) {
|
||||
try {
|
||||
// loop on state.searchRequestTraceIds
|
||||
state.searchRequestTraceIds.forEach((traceId) => {
|
||||
|
||||
@@ -1577,8 +1577,8 @@ const useLogs = () => {
|
||||
// if window has use_web_socket property then use that
|
||||
// else use organization settings
|
||||
searchObj.meta.jobId = "";
|
||||
const shouldUseWebSocket = isWebSocketEnabled();
|
||||
const shouldUseStreaming = isStreamingEnabled();
|
||||
const shouldUseWebSocket = isWebSocketEnabled(store.state);
|
||||
const shouldUseStreaming = isStreamingEnabled(store.state);
|
||||
|
||||
const isMultiStreamSearch =
|
||||
searchObj.data.stream.selectedStream.length > 1 &&
|
||||
|
||||
@@ -184,7 +184,7 @@ const useSearchWebSocket = () => {
|
||||
socketId: socketId.value as string
|
||||
}
|
||||
|
||||
const url = getWebSocketUrl(socketId.value, org_id);
|
||||
const url = getWebSocketUrl(socketId.value, org_id, store.state.API_ENDPOINT);
|
||||
// If needed we can store the socketID in global state
|
||||
webSocket.connect(socketId.value, url);
|
||||
|
||||
|
||||
@@ -15,13 +15,13 @@
|
||||
|
||||
import { describe, expect, it, beforeEach, vi, afterEach } from "vitest";
|
||||
import { flushPromises, mount, shallowMount } from "@vue/test-utils";
|
||||
import { installQuasar } from "../helpers/install-quasar-plugin";
|
||||
import { installQuasar } from "@/test/unit/helpers/install-quasar-plugin";
|
||||
import { Dialog, Notify } from "quasar";
|
||||
import i18n from "@/locales";
|
||||
import store from "../helpers/store";
|
||||
import store from "@/test/unit/helpers/store";
|
||||
import "plotly.js";
|
||||
import MainLayout from "@/layouts/MainLayout.vue";
|
||||
import router from "../helpers/router";
|
||||
import router from "@/test/unit/helpers/router";
|
||||
|
||||
const node = document.createElement("div");
|
||||
node.setAttribute("id", "app");
|
||||
+3
-3
@@ -15,13 +15,13 @@
|
||||
|
||||
import { describe, expect, it, beforeEach, vi, afterEach } from "vitest";
|
||||
import { mount, flushPromises, DOMWrapper } from "@vue/test-utils";
|
||||
import { installQuasar } from "../../helpers/install-quasar-plugin";
|
||||
import { installQuasar } from "@/test/unit/helpers/install-quasar-plugin";
|
||||
import { Dialog, Notify } from "quasar";
|
||||
|
||||
import DetailTable from "@/plugins/logs/DetailTable.vue";
|
||||
import i18n from "@/locales";
|
||||
import store from "../../helpers/store";
|
||||
import router from "../../helpers/router";
|
||||
import store from "@/test/unit/helpers/store";
|
||||
import router from "@/test/unit/helpers/router";
|
||||
|
||||
const node = document.createElement("div");
|
||||
node.setAttribute("id", "app");
|
||||
@@ -15,18 +15,18 @@
|
||||
|
||||
import { describe, expect, it, beforeEach, vi, afterEach } from "vitest";
|
||||
import { mount, flushPromises } from "@vue/test-utils";
|
||||
import { installQuasar } from "../../helpers/install-quasar-plugin";
|
||||
import { installQuasar } from "../../test/unit/helpers/install-quasar-plugin";
|
||||
import { Dialog, Notify } from "quasar";
|
||||
|
||||
import Index from "@/plugins/logs/Index.vue";
|
||||
import i18n from "@/locales";
|
||||
import store from "../../helpers/store";
|
||||
import store from "@/test/unit/helpers/store";
|
||||
// @ts-ignore
|
||||
import { rest } from "msw";
|
||||
import "plotly.js";
|
||||
import SearchResult from "@/plugins/logs/SearchResult.vue";
|
||||
import searchService from "@/services/search";
|
||||
import router from "../../helpers/router";
|
||||
import router from "@/test/unit/helpers/router";
|
||||
|
||||
const node = document.createElement("div");
|
||||
node.setAttribute("id", "app");
|
||||
@@ -1706,8 +1706,8 @@ export default defineComponent({
|
||||
// this.handleRunQuery();
|
||||
this.searchObj.loadingHistogram = true;
|
||||
|
||||
const shouldUseWebSocket = this.isWebSocketEnabled();
|
||||
const shouldUseStreaming = this.isStreamingEnabled();
|
||||
const shouldUseWebSocket = this.isWebSocketEnabled(this.store.state);
|
||||
const shouldUseStreaming = this.isStreamingEnabled(this.store.state);
|
||||
// Generate histogram skeleton before making request
|
||||
await this.generateHistogramSkeleton();
|
||||
|
||||
|
||||
+3
-3
@@ -15,16 +15,16 @@
|
||||
|
||||
import { describe, expect, it, beforeEach, vi, afterEach } from "vitest";
|
||||
import { mount, flushPromises } from "@vue/test-utils";
|
||||
import { installQuasar } from "../../helpers/install-quasar-plugin";
|
||||
import { installQuasar } from "@/test/unit/helpers/install-quasar-plugin";
|
||||
import { Dialog, Notify } from "quasar";
|
||||
|
||||
import Index from "@/plugins/logs/Index.vue";
|
||||
import IndexList from "@/plugins/logs/IndexList.vue";
|
||||
import i18n from "@/locales";
|
||||
import store from "../../helpers/store";
|
||||
import store from "@/test/unit/helpers/store";
|
||||
import "plotly.js";
|
||||
import SearchResult from "@/plugins/logs/SearchResult.vue";
|
||||
import router from "../../helpers/router";
|
||||
import router from "@/test/unit/helpers/router";
|
||||
|
||||
const node = document.createElement("div");
|
||||
node.setAttribute("id", "app");
|
||||
@@ -1020,7 +1020,10 @@ export default defineComponent({
|
||||
query_context = query_context == undefined ? "" : query_context;
|
||||
|
||||
// Implement websocket based field values, check getQueryData in useLogs for websocket enabled
|
||||
if (isWebSocketEnabled() || isStreamingEnabled()) {
|
||||
if (
|
||||
isWebSocketEnabled(store.state) ||
|
||||
isStreamingEnabled(store.state)
|
||||
) {
|
||||
fetchValuesWithWebsocket({
|
||||
fields: [name],
|
||||
size: 10,
|
||||
@@ -1042,19 +1045,25 @@ export default defineComponent({
|
||||
continue;
|
||||
}
|
||||
|
||||
//TODO : add comments for this in future
|
||||
//TODO : add comments for this in future
|
||||
//for future reference
|
||||
//values api using partition based api
|
||||
let queryToBeSent = searchObj.meta.sqlMode ? searchObj.data.query : query_context.replace("[INDEX_NAME]", selectedStream);
|
||||
const response = await getValuesPartition(startISOTimestamp,endISOTimestamp,name,queryToBeSent);
|
||||
let queryToBeSent = searchObj.meta.sqlMode
|
||||
? searchObj.data.query
|
||||
: query_context.replace("[INDEX_NAME]", selectedStream);
|
||||
const response = await getValuesPartition(
|
||||
startISOTimestamp,
|
||||
endISOTimestamp,
|
||||
name,
|
||||
queryToBeSent,
|
||||
);
|
||||
const partitions: any = response?.data.partitions || [];
|
||||
|
||||
|
||||
for (const partition of partitions) {
|
||||
try {
|
||||
//check if the field is opened because sometimes
|
||||
//check if the field is opened because sometimes
|
||||
// user might close the field before all the subsequent requests are completed
|
||||
if(!openedFilterFields.value.includes(name)){
|
||||
if (!openedFilterFields.value.includes(name)) {
|
||||
return;
|
||||
}
|
||||
const res: any = await streamService.fieldValues({
|
||||
@@ -1085,7 +1094,8 @@ export default defineComponent({
|
||||
(value: any) => value.key === subItem.zo_sql_key,
|
||||
);
|
||||
if (index !== -1) {
|
||||
fieldValues.value[name]["values"][index].count += parseInt(subItem.zo_sql_num);
|
||||
fieldValues.value[name]["values"][index].count +=
|
||||
parseInt(subItem.zo_sql_num);
|
||||
} else {
|
||||
fieldValues.value[name]["values"].push({
|
||||
key: subItem.zo_sql_key,
|
||||
@@ -1096,8 +1106,12 @@ export default defineComponent({
|
||||
});
|
||||
|
||||
if (fieldValues.value[name]["values"].length > 10) {
|
||||
fieldValues.value[name]["values"].sort((a, b) => b.count - a.count);
|
||||
fieldValues.value[name]["values"] = fieldValues.value[name]["values"].slice(0, 10);
|
||||
fieldValues.value[name]["values"].sort(
|
||||
(a, b) => b.count - a.count,
|
||||
);
|
||||
fieldValues.value[name]["values"] = fieldValues.value[name][
|
||||
"values"
|
||||
].slice(0, 10);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
@@ -1110,13 +1124,16 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
}
|
||||
openedFilterFields.value = openedFilterFields.value.filter((field:string)=>field !== name);
|
||||
|
||||
openedFilterFields.value = openedFilterFields.value.filter(
|
||||
(field: string) => field !== name,
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
fieldValues.value[name]["isLoading"] = false;
|
||||
openedFilterFields.value = openedFilterFields.value.filter((field:string)=>field !== name);
|
||||
openedFilterFields.value = openedFilterFields.value.filter(
|
||||
(field: string) => field !== name,
|
||||
);
|
||||
console.log(err);
|
||||
$q.notify({
|
||||
type: "negative",
|
||||
@@ -1298,7 +1315,7 @@ export default defineComponent({
|
||||
};
|
||||
|
||||
const initializeWebSocketConnection = (payload: any) => {
|
||||
if (isWebSocketEnabled()) {
|
||||
if (isWebSocketEnabled(store.state)) {
|
||||
fetchQueryDataWithWebSocket(payload, {
|
||||
open: sendSearchMessage,
|
||||
close: handleSearchClose,
|
||||
@@ -1309,7 +1326,7 @@ export default defineComponent({
|
||||
return;
|
||||
}
|
||||
|
||||
if (isStreamingEnabled()) {
|
||||
if (isStreamingEnabled(store.state)) {
|
||||
fetchQueryDataWithHttpStream(payload, {
|
||||
data: handleSearchResponse,
|
||||
error: handleSearchError,
|
||||
@@ -1488,17 +1505,15 @@ export default defineComponent({
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const cancelFilterCreator = (row: any) => {
|
||||
//if it is websocker based then cancel the trace id
|
||||
//else cancel the further value api calls using the openedFilterFields
|
||||
if(isWebSocketEnabled()){
|
||||
if (isWebSocketEnabled(store.state)) {
|
||||
cancelTraceId(row.name);
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
cancelValueApi(row.name);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const cancelTraceId = (field: string) => {
|
||||
const traceIds = traceIdMapper.value[field];
|
||||
@@ -1513,30 +1528,36 @@ export default defineComponent({
|
||||
};
|
||||
const cancelValueApi = (value: string) => {
|
||||
//remove the field from the openedFilterFields
|
||||
openedFilterFields.value = openedFilterFields.value.filter((field:string)=>field !== value);
|
||||
}
|
||||
const getValuesPartition = async (start: number, end: number,name:string,queryToBeSent:string) => {
|
||||
try{
|
||||
const queryReq = {
|
||||
sql: queryToBeSent,
|
||||
start_time: start,
|
||||
end_time: end,
|
||||
sql_mode: "context",
|
||||
// streaming_output: true,
|
||||
}
|
||||
const res = await searchService.partition({
|
||||
org_identifier: store.state.selectedOrganization.identifier,
|
||||
query: queryReq,
|
||||
page_type: searchObj.data.stream.streamType,
|
||||
traceparent: generateTraceContext().traceId,
|
||||
});
|
||||
|
||||
return res;
|
||||
openedFilterFields.value = openedFilterFields.value.filter(
|
||||
(field: string) => field !== value,
|
||||
);
|
||||
};
|
||||
const getValuesPartition = async (
|
||||
start: number,
|
||||
end: number,
|
||||
name: string,
|
||||
queryToBeSent: string,
|
||||
) => {
|
||||
try {
|
||||
const queryReq = {
|
||||
sql: queryToBeSent,
|
||||
start_time: start,
|
||||
end_time: end,
|
||||
sql_mode: "context",
|
||||
// streaming_output: true,
|
||||
};
|
||||
const res = await searchService.partition({
|
||||
org_identifier: store.state.selectedOrganization.identifier,
|
||||
query: queryReq,
|
||||
page_type: searchObj.data.stream.streamType,
|
||||
traceparent: generateTraceContext().traceId,
|
||||
});
|
||||
|
||||
return res;
|
||||
} catch (err) {
|
||||
console.error("Failed to fetch field values:", err);
|
||||
fieldValues.value[name].errMsg = "Failed to fetch field values";
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
return {
|
||||
@@ -1610,7 +1631,7 @@ export default defineComponent({
|
||||
sortedStreamFields,
|
||||
placeHolderText,
|
||||
cancelTraceId,
|
||||
cancelFilterCreator
|
||||
cancelFilterCreator,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
+3
-3
@@ -15,14 +15,14 @@
|
||||
|
||||
import { describe, expect, it, beforeEach, vi, afterEach } from "vitest";
|
||||
import { mount, flushPromises } from "@vue/test-utils";
|
||||
import { installQuasar } from "../../helpers/install-quasar-plugin";
|
||||
import { installQuasar } from "@/test/unit/helpers/install-quasar-plugin";
|
||||
import { Dialog, Notify } from "quasar";
|
||||
|
||||
import QueryEditor from "@/components/QueryEditor.vue";
|
||||
import i18n from "@/locales";
|
||||
import store from "../../helpers/store";
|
||||
import store from "@/test/unit/helpers/store";
|
||||
import "plotly.js";
|
||||
import router from "../../helpers/router";
|
||||
import router from "@/test/unit/helpers/router";
|
||||
|
||||
const node = document.createElement("div");
|
||||
node.setAttribute("id", "app");
|
||||
+3
-4
@@ -15,17 +15,16 @@
|
||||
|
||||
import { describe, expect, it, beforeEach, vi, afterEach } from "vitest";
|
||||
import { mount, flushPromises, DOMWrapper } from "@vue/test-utils";
|
||||
import { installQuasar } from "../../helpers/install-quasar-plugin";
|
||||
import { installQuasar } from "@/test/unit/helpers/install-quasar-plugin";
|
||||
import { Dialog, Notify } from "quasar";
|
||||
|
||||
import Index from "@/plugins/logs/Index.vue";
|
||||
import SearchBar from "@/plugins/logs/SearchBar.vue";
|
||||
import i18n from "@/locales";
|
||||
import store from "../../helpers/store";
|
||||
import "plotly.js";
|
||||
import store from "@/test/unit/helpers/store";
|
||||
import searchService from "@/services/search";
|
||||
import SearchResult from "@/plugins/logs/SearchResult.vue";
|
||||
import router from "../../helpers/router";
|
||||
import router from "@/test/unit/helpers/router";
|
||||
|
||||
const node = document.createElement("div");
|
||||
node.setAttribute("id", "app");
|
||||
+3
-3
@@ -15,19 +15,19 @@
|
||||
|
||||
import { describe, expect, it, beforeEach, vi, afterEach } from "vitest";
|
||||
import { mount, flushPromises } from "@vue/test-utils";
|
||||
import { installQuasar } from "../../helpers/install-quasar-plugin";
|
||||
import { installQuasar } from "@/test/unit/helpers/install-quasar-plugin";
|
||||
import { Dialog, Notify } from "quasar";
|
||||
|
||||
import Index from "@/plugins/logs/Index.vue";
|
||||
import SearchResult from "@/plugins/logs/SearchResult.vue";
|
||||
// import BarChart from "@/components/logBarChart.vue";
|
||||
import i18n from "@/locales";
|
||||
import store from "../../helpers/store";
|
||||
import store from "@/test/unit/helpers/store";
|
||||
// @ts-ignore
|
||||
import { rest } from "msw";
|
||||
// import "plotly.js";
|
||||
import DetailTable from "@/plugins/logs/DetailTable.vue";
|
||||
import router from "../../helpers/router";
|
||||
import router from "@/test/unit/helpers/router";
|
||||
|
||||
const node = document.createElement("div");
|
||||
node.setAttribute("id", "app");
|
||||
@@ -1 +1,16 @@
|
||||
// Copyright 2023 OpenObserve Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import "vitest-canvas-mock";
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
// Copyright 2023 OpenObserve Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { vi } from "vitest";
|
||||
|
||||
vi.stubGlobal("open", vi.fn());
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
// Copyright 2023 OpenObserve Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { vi } from "vitest";
|
||||
import axios from "axios";
|
||||
import { Notify } from "quasar"; // ✅ Ensure Quasar Notify works in mock
|
||||
|
||||
vi.mock("@/services/http.ts", () => ({
|
||||
default: () => {
|
||||
const instance = axios.create({
|
||||
withCredentials: true,
|
||||
baseURL: "http://localhost:5080", // 🔹 Replacing `store.state.API_ENDPOINT`
|
||||
});
|
||||
|
||||
// Mock request interceptor
|
||||
instance.interceptors.request.use(
|
||||
(config) => {
|
||||
return config;
|
||||
},
|
||||
(error) => Promise.reject(error),
|
||||
);
|
||||
|
||||
// Mock response interceptor with error handling
|
||||
instance.interceptors.response.use(
|
||||
(response) => response,
|
||||
(error) => {
|
||||
console.error("Mock Interceptor Error", error);
|
||||
|
||||
if (error?.response?.status === 400) {
|
||||
return Promise.reject({
|
||||
response: { status: 400, data: "Bad Request" },
|
||||
});
|
||||
}
|
||||
|
||||
if (error?.response?.status === 401) {
|
||||
console.log("Mock 401: Unauthorized - Logging out user...");
|
||||
sessionStorage.clear(); // Simulate logout
|
||||
return Promise.reject({
|
||||
response: { status: 401, data: "Unauthorized" },
|
||||
});
|
||||
}
|
||||
|
||||
if (error?.response?.status === 403) {
|
||||
console.log("Mock 403: Forbidden - Showing notification...");
|
||||
Notify.create({
|
||||
message: "Unauthorized Access: Please contact your administrator.",
|
||||
color: "negative",
|
||||
timeout: 0,
|
||||
});
|
||||
return Promise.reject({
|
||||
response: { status: 403, data: "Forbidden" },
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.reject({
|
||||
response: { status: 500, data: "Internal Server Error" },
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
return instance;
|
||||
},
|
||||
}));
|
||||
@@ -1,4 +1,19 @@
|
||||
// Copyright 2023 OpenObserve Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import "./canvas";
|
||||
import "./plotly";
|
||||
import "./global";
|
||||
import "./rudder-sdk";
|
||||
import "./http";
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
import { vi } from "vitest";
|
||||
|
||||
vi.mock("plotly.js", () => {
|
||||
return {
|
||||
default: {
|
||||
newPlot: vi.fn((ref) => {
|
||||
ref.on = vi.fn();
|
||||
}),
|
||||
addTraces: vi.fn(),
|
||||
restyle: vi.fn(),
|
||||
relayout: vi.fn(),
|
||||
redraw: vi.fn(),
|
||||
},
|
||||
};
|
||||
});
|
||||
@@ -1,3 +1,18 @@
|
||||
// Copyright 2023 OpenObserve Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { vi } from "vitest";
|
||||
|
||||
vi.mock("rudder-sdk-js", () => {
|
||||
|
||||
@@ -1,192 +0,0 @@
|
||||
// Copyright 2023 OpenObserve Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { describe, expect, it, beforeEach, vi, afterEach } from "vitest";
|
||||
import { mount, flushPromises, DOMWrapper } from "@vue/test-utils";
|
||||
import { installQuasar } from "../../helpers/install-quasar-plugin";
|
||||
import { Dialog, Notify } from "quasar";
|
||||
import AddAlert from "@/components/alerts/AddAlert.vue";
|
||||
import i18n from "@/locales";
|
||||
import store from "../../helpers/store";
|
||||
import AlertService from "@/services/alerts";
|
||||
// @ts-ignore
|
||||
import { rest } from "msw";
|
||||
import router from "../../helpers/router";
|
||||
|
||||
installQuasar({
|
||||
plugins: [Dialog, Notify],
|
||||
});
|
||||
|
||||
const node = document.createElement("div");
|
||||
node.setAttribute("id", "app");
|
||||
document.body.appendChild(node);
|
||||
|
||||
describe("Alert List", async () => {
|
||||
let wrapper: any;
|
||||
beforeEach(async () => {
|
||||
vi.useFakeTimers();
|
||||
wrapper = mount(AddAlert, {
|
||||
attachTo: "#app",
|
||||
global: {
|
||||
provide: {
|
||||
store: store,
|
||||
},
|
||||
plugins: [i18n, router],
|
||||
},
|
||||
});
|
||||
await flushPromises();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
it("Should render alerts title", () => {
|
||||
expect(wrapper.find('[data-test="add-alert-title"]').text()).toBe(
|
||||
"Add Alert"
|
||||
);
|
||||
});
|
||||
|
||||
it("Should render name input", () => {
|
||||
expect(
|
||||
wrapper.find('[data-test="add-alert-name-input"]').exists()
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
it("Should render stream input", () => {
|
||||
expect(
|
||||
wrapper.find('[data-test="add-alert-stream-select"]').exists()
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
it("Should by default select Scheduled type alerts", () => {
|
||||
expect(
|
||||
wrapper
|
||||
.find('[data-test="add-alert-scheduled-alert-radio"]')
|
||||
.find(".q-radio__inner--truthy")
|
||||
.exists()
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
it("Should reder condition", () => {
|
||||
expect(wrapper.find('[data-test="add-alert-condition-title"]').text()).toBe(
|
||||
"Condition:"
|
||||
);
|
||||
expect(
|
||||
wrapper.find('[data-test="add-alert-condition-column-select"]').exists()
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
wrapper.find('[data-test="add-alert-condition-operator-select"]').exists()
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
wrapper.find('[data-test="add-alert-condition-value-input"]').exists()
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
it("Should reder sql query input", () => {
|
||||
expect(
|
||||
wrapper.find('[data-test="add-alert-query-input-title"]').text()
|
||||
).toBe("Query:");
|
||||
expect(
|
||||
wrapper.find('[data-test="add-alert-query-input"]').exists()
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
it("Should reder Duration input", () => {
|
||||
expect(wrapper.find('[data-test="add-alert-duration-title"]').text()).toBe(
|
||||
"Duration for which alert is evaluated:"
|
||||
);
|
||||
expect(
|
||||
wrapper.find('[data-test="add-alert-duration-input"]').exists()
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
wrapper.find('[data-test="add-alert-duration-select"]').exists()
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
it("Should reder Frequency input", () => {
|
||||
expect(wrapper.find('[data-test="add-alert-frequency-title"]').text()).toBe(
|
||||
"Frequency at which alert is evaluated:"
|
||||
);
|
||||
expect(
|
||||
wrapper.find('[data-test="add-alert-frequency-input"]').exists()
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
wrapper.find('[data-test="add-alert-frequency-select"]').exists()
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
it("Should reder Delay notification input", () => {
|
||||
expect(wrapper.find('[data-test="add-alert-delay-title"]').text()).toBe(
|
||||
"Delay notification until, after one notification:"
|
||||
);
|
||||
expect(
|
||||
wrapper.find('[data-test="add-alert-delay-input"]').exists()
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
wrapper.find('[data-test="add-alert-delay-select"]').exists()
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
it("Should reder destination select input", () => {
|
||||
expect(
|
||||
wrapper.find('[data-test="add-alert-destination-select"]').exists()
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
describe("When user fills form and clicks submit", () => {
|
||||
const submitBtn = vi.spyOn(AlertService, "create");
|
||||
const stream_name = "k8s_json";
|
||||
const alert_name = "alert1";
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
beforeEach(async () => {
|
||||
global.server.use(
|
||||
rest.post(
|
||||
`${store.state.API_ENDPOINT}/api/${store.state.selectedOrganization.identifier}/${stream_name}/alerts/${alert_name}`,
|
||||
(req: any, res: any, ctx: any) => {
|
||||
return res(ctx.status(200), ctx.json({ code: 200 }));
|
||||
}
|
||||
)
|
||||
);
|
||||
await wrapper
|
||||
.find('[data-test="add-alert-name-input"]')
|
||||
.setValue(alert_name);
|
||||
wrapper.vm.formData.stream_name = stream_name;
|
||||
wrapper.vm.formData.condition.column = "kubernetes.host";
|
||||
wrapper.vm.formData.condition.operator = "=";
|
||||
await wrapper
|
||||
.find('[data-test="add-alert-condition-value-input"]')
|
||||
.setValue("abc");
|
||||
await wrapper.find('[data-test="add-alert-duration-input"]').setValue(1);
|
||||
await wrapper.find('[data-test="add-alert-frequency-input"]').setValue(1);
|
||||
await wrapper.find('[data-test="add-alert-delay-input"]').setValue(1);
|
||||
wrapper.vm.formData.destination = "dest1";
|
||||
});
|
||||
|
||||
it("Should create alert on clicking Submit", async () => {
|
||||
await wrapper.find('[data-test="add-alert-submit-btn"]').trigger("click");
|
||||
await flushPromises();
|
||||
expect(submitBtn).toHaveBeenCalledTimes(1);
|
||||
expect(wrapper.emitted()["update:list"]).toHaveLength(1);
|
||||
});
|
||||
|
||||
it("Should create alert on clicking Submit", async () => {
|
||||
await wrapper.find('[data-test="add-alert-cancel-btn"]').trigger("click");
|
||||
expect(wrapper.emitted()["cancel:hideform"]).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,37 +0,0 @@
|
||||
// Vitest Snapshot v1
|
||||
|
||||
exports[`Alert List > Should match previous table snapshot 1`] = `
|
||||
"<table class=\\"q-table\\">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class=\\"text-left\\">#</th>
|
||||
<th class=\\"text-left sortable\\">Name<i class=\\"q-icon notranslate material-icons q-table__sort-icon q-table__sort-icon--left\\" aria-hidden=\\"true\\" role=\\"presentation\\">arrow_upward</i></th>
|
||||
<th class=\\"text-left sortable\\">Stream Name<i class=\\"q-icon notranslate material-icons q-table__sort-icon q-table__sort-icon--left\\" aria-hidden=\\"true\\" role=\\"presentation\\">arrow_upward</i></th>
|
||||
<th class=\\"text-left sortable\\">Query<i class=\\"q-icon notranslate material-icons q-table__sort-icon q-table__sort-icon--left\\" aria-hidden=\\"true\\" role=\\"presentation\\">arrow_upward</i></th>
|
||||
<th class=\\"text-left sortable\\">Condition<i class=\\"q-icon notranslate material-icons q-table__sort-icon q-table__sort-icon--left\\" aria-hidden=\\"true\\" role=\\"presentation\\">arrow_upward</i></th>
|
||||
<th class=\\"text-left sortable\\">Destination<i class=\\"q-icon notranslate material-icons q-table__sort-icon q-table__sort-icon--left\\" aria-hidden=\\"true\\" role=\\"presentation\\">arrow_upward</i></th>
|
||||
<th class=\\"text-center\\">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class=\\"\\">
|
||||
<td class=\\"text-left\\">01</td>
|
||||
<td class=\\"text-left\\">alert1</td>
|
||||
<td class=\\"text-left\\">default</td>
|
||||
<td class=\\"text-left\\" style=\\"width: 30vw; word-break: break-all;\\">--</td>
|
||||
<td class=\\"text-left\\" style=\\"width: 10vw; word-break: break-all;\\">code EqualTo 500</td>
|
||||
<td class=\\"text-left\\">dest1</td>
|
||||
<td class=\\"q-td text-center\\"><button class=\\"q-btn q-btn-item non-selectable no-outline q-btn--flat q-btn--round q-btn--actionable q-focusable q-hoverable q-ml-xs iconHoverBtn\\" style=\\"font-size: 10px; padding: 8px; min-width: 0; min-height: 0;\\" tabindex=\\"0\\" type=\\"button\\" data-test=\\"alert-list-alert1-delete-alert\\" title=\\"Edit\\"><span class=\\"q-focus-helper\\"></span><span class=\\"q-btn__content text-center col items-center q-anchor--skip justify-center row\\"><i class=\\"q-icon notranslate material-icons\\" aria-hidden=\\"true\\" role=\\"img\\">edit</i></span></button><button class=\\"q-btn q-btn-item non-selectable no-outline q-btn--flat q-btn--round q-btn--actionable q-focusable q-hoverable q-ml-xs iconHoverBtn\\" style=\\"font-size: 10px; padding: 8px; min-width: 0; min-height: 0;\\" tabindex=\\"0\\" type=\\"button\\" title=\\"Delete\\"><span class=\\"q-focus-helper\\"></span><span class=\\"q-btn__content text-center col items-center q-anchor--skip justify-center row\\"><span class=\\"q-icon\\" aria-hidden=\\"true\\" role=\\"img\\"><img src=\\"/src/assets/images/common/delete_icon.svg\\"></span></span></button></td>
|
||||
</tr>
|
||||
<tr class=\\"\\">
|
||||
<td class=\\"text-left\\">02</td>
|
||||
<td class=\\"text-left\\">alert2</td>
|
||||
<td class=\\"text-left\\">default</td>
|
||||
<td class=\\"text-left\\" style=\\"width: 30vw; word-break: break-all;\\">select * from 'default'</td>
|
||||
<td class=\\"text-left\\" style=\\"width: 10vw; word-break: break-all;\\">code EqualTo 500</td>
|
||||
<td class=\\"text-left\\">dest1</td>
|
||||
<td class=\\"q-td text-center\\"><button class=\\"q-btn q-btn-item non-selectable no-outline q-btn--flat q-btn--round q-btn--actionable q-focusable q-hoverable q-ml-xs iconHoverBtn\\" style=\\"font-size: 10px; padding: 8px; min-width: 0; min-height: 0;\\" tabindex=\\"0\\" type=\\"button\\" data-test=\\"alert-list-alert2-delete-alert\\" title=\\"Edit\\"><span class=\\"q-focus-helper\\"></span><span class=\\"q-btn__content text-center col items-center q-anchor--skip justify-center row\\"><i class=\\"q-icon notranslate material-icons\\" aria-hidden=\\"true\\" role=\\"img\\">edit</i></span></button><button class=\\"q-btn q-btn-item non-selectable no-outline q-btn--flat q-btn--round q-btn--actionable q-focusable q-hoverable q-ml-xs iconHoverBtn\\" style=\\"font-size: 10px; padding: 8px; min-width: 0; min-height: 0;\\" tabindex=\\"0\\" type=\\"button\\" title=\\"Delete\\"><span class=\\"q-focus-helper\\"></span><span class=\\"q-btn__content text-center col items-center q-anchor--skip justify-center row\\"><span class=\\"q-icon\\" aria-hidden=\\"true\\" role=\\"img\\"><img src=\\"/src/assets/images/common/delete_icon.svg\\"></span></span></button></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>"
|
||||
`;
|
||||
@@ -1,37 +0,0 @@
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`Alert List > Should match previous table snapshot 1`] = `
|
||||
"<table class=\\"q-table\\">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class=\\"text-left\\">#</th>
|
||||
<th class=\\"text-left sortable\\">Name<i class=\\"q-icon notranslate material-icons q-table__sort-icon q-table__sort-icon--left\\" aria-hidden=\\"true\\" role=\\"presentation\\">arrow_upward</i></th>
|
||||
<th class=\\"text-left sortable\\">Stream Name<i class=\\"q-icon notranslate material-icons q-table__sort-icon q-table__sort-icon--left\\" aria-hidden=\\"true\\" role=\\"presentation\\">arrow_upward</i></th>
|
||||
<th class=\\"text-left sortable\\">Query<i class=\\"q-icon notranslate material-icons q-table__sort-icon q-table__sort-icon--left\\" aria-hidden=\\"true\\" role=\\"presentation\\">arrow_upward</i></th>
|
||||
<th class=\\"text-left sortable\\">Condition<i class=\\"q-icon notranslate material-icons q-table__sort-icon q-table__sort-icon--left\\" aria-hidden=\\"true\\" role=\\"presentation\\">arrow_upward</i></th>
|
||||
<th class=\\"text-left sortable\\">Destination<i class=\\"q-icon notranslate material-icons q-table__sort-icon q-table__sort-icon--left\\" aria-hidden=\\"true\\" role=\\"presentation\\">arrow_upward</i></th>
|
||||
<th class=\\"text-center\\">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class=\\"\\">
|
||||
<td class=\\"text-left\\">01</td>
|
||||
<td class=\\"text-left\\">alert1</td>
|
||||
<td class=\\"text-left\\">default</td>
|
||||
<td class=\\"text-left\\" style=\\"width: 30vw; word-break: break-all;\\">--</td>
|
||||
<td class=\\"text-left\\" style=\\"width: 10vw; word-break: break-all;\\">code EqualTo 500</td>
|
||||
<td class=\\"text-left\\">dest1</td>
|
||||
<td class=\\"q-td text-center\\"><button class=\\"q-btn q-btn-item non-selectable no-outline q-btn--flat q-btn--round q-btn--actionable q-focusable q-hoverable q-ml-xs iconHoverBtn\\" style=\\"font-size: 10px; padding: 8px; min-width: 0; min-height: 0;\\" tabindex=\\"0\\" type=\\"button\\" title=\\"Edit\\"><span class=\\"q-focus-helper\\"></span><span class=\\"q-btn__content text-center col items-center q-anchor--skip justify-center row\\"><i class=\\"q-icon notranslate material-icons\\" aria-hidden=\\"true\\" role=\\"img\\">edit</i></span></button><button class=\\"q-btn q-btn-item non-selectable no-outline q-btn--flat q-btn--round q-btn--actionable q-focusable q-hoverable q-ml-xs iconHoverBtn\\" style=\\"font-size: 10px; padding: 8px; min-width: 0; min-height: 0;\\" tabindex=\\"0\\" type=\\"button\\" title=\\"Delete\\"><span class=\\"q-focus-helper\\"></span><span class=\\"q-btn__content text-center col items-center q-anchor--skip justify-center row\\"><span class=\\"q-icon\\" aria-hidden=\\"true\\" role=\\"img\\"><img src=\\"/src/assets/images/common/delete_icon.svg\\"></span></span></button></td>
|
||||
</tr>
|
||||
<tr class=\\"\\">
|
||||
<td class=\\"text-left\\">02</td>
|
||||
<td class=\\"text-left\\">alert2</td>
|
||||
<td class=\\"text-left\\">default</td>
|
||||
<td class=\\"text-left\\" style=\\"width: 30vw; word-break: break-all;\\">select * from 'default'</td>
|
||||
<td class=\\"text-left\\" style=\\"width: 10vw; word-break: break-all;\\">code EqualTo 500</td>
|
||||
<td class=\\"text-left\\">dest1</td>
|
||||
<td class=\\"q-td text-center\\"><button class=\\"q-btn q-btn-item non-selectable no-outline q-btn--flat q-btn--round q-btn--actionable q-focusable q-hoverable q-ml-xs iconHoverBtn\\" style=\\"font-size: 10px; padding: 8px; min-width: 0; min-height: 0;\\" tabindex=\\"0\\" type=\\"button\\" title=\\"Edit\\"><span class=\\"q-focus-helper\\"></span><span class=\\"q-btn__content text-center col items-center q-anchor--skip justify-center row\\"><i class=\\"q-icon notranslate material-icons\\" aria-hidden=\\"true\\" role=\\"img\\">edit</i></span></button><button class=\\"q-btn q-btn-item non-selectable no-outline q-btn--flat q-btn--round q-btn--actionable q-focusable q-hoverable q-ml-xs iconHoverBtn\\" style=\\"font-size: 10px; padding: 8px; min-width: 0; min-height: 0;\\" tabindex=\\"0\\" type=\\"button\\" title=\\"Delete\\"><span class=\\"q-focus-helper\\"></span><span class=\\"q-btn__content text-center col items-center q-anchor--skip justify-center row\\"><span class=\\"q-icon\\" aria-hidden=\\"true\\" role=\\"img\\"><img src=\\"/src/assets/images/common/delete_icon.svg\\"></span></span></button></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>"
|
||||
`;
|
||||
@@ -1,3 +0,0 @@
|
||||
// Vitest Snapshot v1
|
||||
|
||||
exports[`Curl > should render content 1`] = `"curl -u example@gmail.com:11 -k http://localhost:8080/api/zinc_next/default/_json -d [JSON-DATA]"`;
|
||||
@@ -1,16 +0,0 @@
|
||||
// Vitest Snapshot v1
|
||||
|
||||
exports[`FluentBit > should render content 1`] = `
|
||||
"[OUTPUT]
|
||||
Name http
|
||||
Match *
|
||||
URI /api/zinc_next/default/_json
|
||||
Host localhost
|
||||
Port 808
|
||||
tls Off
|
||||
Format json
|
||||
Json_date_key _timestamp
|
||||
Json_date_format iso8601
|
||||
HTTP_User tulsiraval2828@gmail.com
|
||||
HTTP_Passwd 11"
|
||||
`;
|
||||
@@ -1,21 +0,0 @@
|
||||
// Vitest Snapshot v1
|
||||
|
||||
exports[`Fluentd > should render content 1`] = `
|
||||
"<source>
|
||||
@type forward
|
||||
port 24224
|
||||
bind 0.0.0.0
|
||||
</source>
|
||||
|
||||
<match **>
|
||||
@type http
|
||||
endpoint http://localhost:808/api/zinc_next/default/_json
|
||||
content_type json
|
||||
json_array true
|
||||
<auth>
|
||||
method basic
|
||||
username tulsiraval2828@gmail.com
|
||||
password 11
|
||||
</auth>
|
||||
</match>"
|
||||
`;
|
||||
@@ -1,16 +0,0 @@
|
||||
// Vitest Snapshot v1
|
||||
|
||||
exports[`Vector > should render content 1`] = `
|
||||
"[sinks.openobserve]
|
||||
type = \\"http\\"
|
||||
inputs = [ source or transform id ]
|
||||
uri = \\"http://localhost:808/api/zinc_next/default/_json\\"
|
||||
method = \\"post\\"
|
||||
auth.strategy = \\"basic\\"
|
||||
auth.user = \\"tulsiraval2828@gmail.com\\"
|
||||
auth.password = \\"11\\"
|
||||
compression = \\"gzip\\"
|
||||
encoding.codec = \\"json\\"
|
||||
encoding.timestamp_format = \\"rfc3339\\"
|
||||
healthcheck.enabled = false"
|
||||
`;
|
||||
@@ -1,211 +0,0 @@
|
||||
import { describe, expect, it, beforeEach, vi, afterEach } from "vitest";
|
||||
import { mount, flushPromises } from "@vue/test-utils";
|
||||
import { installQuasar } from "../../helpers/install-quasar-plugin";
|
||||
import { Dialog, Notify } from "quasar";
|
||||
import LogStream from "@/components/logstream/schema.vue";
|
||||
import i18n from "@/locales";
|
||||
// @ts-ignore
|
||||
import { rest } from "msw";
|
||||
import store from "@/test/unit/helpers/store";
|
||||
import StreamService from "@/services/stream";
|
||||
|
||||
installQuasar({
|
||||
plugins: [Dialog, Notify],
|
||||
});
|
||||
|
||||
describe("Streams", async () => {
|
||||
let wrapper: any;
|
||||
|
||||
beforeEach(async () => {
|
||||
vi.useFakeTimers();
|
||||
|
||||
wrapper = mount(LogStream, {
|
||||
props: {
|
||||
modelValue: {
|
||||
name: "k8s_json",
|
||||
schema: [],
|
||||
stream_type: "logs",
|
||||
},
|
||||
},
|
||||
global: {
|
||||
provide: {
|
||||
store: store,
|
||||
},
|
||||
plugins: [i18n],
|
||||
},
|
||||
});
|
||||
await flushPromises();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.unmount();
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it("should display title", () => {
|
||||
const pageTitle = wrapper.find('[data-test="schema-title-text"]');
|
||||
expect(pageTitle.text()).toBe("Stream Detail");
|
||||
});
|
||||
|
||||
it("Should display stream title", () => {
|
||||
const streamTitle = wrapper.find('[data-test="schema-stream-title-text"]');
|
||||
expect(streamTitle.text()).toBe("k8s_json");
|
||||
});
|
||||
|
||||
it("Should have cancel button", () => {
|
||||
const cancelButton = wrapper.find('[data-test="schema-cancel-button"]');
|
||||
expect(cancelButton.exists()).toBeTruthy();
|
||||
expect(cancelButton.text()).toBe("Cancel");
|
||||
});
|
||||
|
||||
it("Should have Update Settings button", () => {
|
||||
const updateSettingsButton = wrapper.find(
|
||||
'[data-test="schema-update-settings-button"]',
|
||||
);
|
||||
expect(updateSettingsButton.exists()).toBeTruthy();
|
||||
expect(updateSettingsButton.text()).toBe("Update Settings");
|
||||
});
|
||||
|
||||
it("Should have Cancel button ", () => {
|
||||
const table = wrapper.find('[data-test="schema-stream-meta-data-table"]');
|
||||
expect(table.exists()).toBeTruthy();
|
||||
});
|
||||
|
||||
it("Should display stream meta data table header", () => {
|
||||
store.state.zoConfig.show_stream_stats_doc_num = true;
|
||||
const tableHeaders = wrapper
|
||||
.find('[data-test="schema-stream-meta-data-table"]')
|
||||
.find("thead")
|
||||
.find("tr")
|
||||
.findAll("th");
|
||||
|
||||
expect(tableHeaders[0].text()).toBe("Docs Count");
|
||||
expect(tableHeaders[1].text()).toBe("Ingested Data");
|
||||
expect(tableHeaders[2].text()).toBe("Compressed Size");
|
||||
expect(tableHeaders[3].text()).toBe("Time");
|
||||
});
|
||||
|
||||
it("Should display stream meta data table data", () => {
|
||||
const tableHeaders = wrapper
|
||||
.find('[data-test="schema-stream-meta-data-table"]')
|
||||
.find("tbody")
|
||||
.find("tr")
|
||||
.findAll("td");
|
||||
expect(tableHeaders[0].text()).toBe("400");
|
||||
expect(tableHeaders[1].text()).toBe("0.74 MB");
|
||||
expect(tableHeaders[2].text()).toBe("0.03 MB");
|
||||
expect(tableHeaders[3].text()).toBe(
|
||||
"2023-03-10T17:13:48:63+05:30 to 2023-03-10T17:13:48:65+05:30",
|
||||
);
|
||||
});
|
||||
|
||||
it("Should display stream fields mapping table", () => {
|
||||
const table = wrapper.find(
|
||||
'[data-test="schema-log-stream-field-mapping-table"]',
|
||||
);
|
||||
expect(table.exists()).toBeTruthy();
|
||||
});
|
||||
|
||||
it("Should display stream fields mapping title", () => {
|
||||
const table = wrapper.find(
|
||||
'[data-test="schema-log-stream-mapping-title-text"]',
|
||||
);
|
||||
expect(table.text()).toBe(
|
||||
"Mapping - Using default fts keys, as no fts keys are set for stream.Store Original Data",
|
||||
);
|
||||
});
|
||||
|
||||
it("Should display stream fields mapping table headers", () => {
|
||||
const tableHeaders = wrapper
|
||||
.find('[data-test="schema-log-stream-field-mapping-table"]')
|
||||
.find("thead")
|
||||
.find("tr")
|
||||
.findAll("th");
|
||||
|
||||
expect(tableHeaders[0].text()).toBe("");
|
||||
expect(tableHeaders[1].text()).toBe("Fieldarrow_upward");
|
||||
expect(tableHeaders[2].text()).toBe("Typearrow_upward");
|
||||
expect(tableHeaders[3].text()).toBe("Index Type");
|
||||
});
|
||||
|
||||
it("Should display stream fields mapping table data", () => {
|
||||
const tableData = wrapper
|
||||
.find('[data-test="schema-log-stream-field-mapping-table"]')
|
||||
.find("tbody")
|
||||
.findAll("tr")[0]
|
||||
.findAll("td");
|
||||
|
||||
expect(tableData[0].text()).toBe("");
|
||||
expect(tableData[1].text()).toBe("_timestamp");
|
||||
expect(tableData[2].text()).toBe("Int64");
|
||||
});
|
||||
|
||||
// TODO : Check if we can update this test case
|
||||
// - expect(logCheckbox.find(".q-checkbox__inner--truthy").exists()).toBeTruthy();
|
||||
// + expect(wrapper.vm.ftsKeys.includes('log')).toBeTruthy();
|
||||
it("Should check if log and message full text search checkbox is active in field mapping table", () => {
|
||||
const logCheckbox = wrapper
|
||||
.find('[data-test="schema-log-stream-field-mapping-table"]')
|
||||
.find('[data-test="schema-stream-log-field-fts-key-checkbox"]');
|
||||
const messageCheckbox = wrapper
|
||||
.find('[data-test="schema-log-stream-field-mapping-table"]')
|
||||
.find("tbody")
|
||||
.find('[data-test="schema-stream-log-field-fts-key-checkbox"]');
|
||||
expect(
|
||||
logCheckbox.find(".q-checkbox__inner--truthy").exists(),
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
messageCheckbox.find(".q-checkbox__inner--truthy").exists(),
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
it("Should check if _timestamp and kubernetes.container_hash full text search checkbox is inactive in field mapping table", () => {
|
||||
const timeStampCheckbox = wrapper
|
||||
.find('[data-test="schema-log-stream-field-mapping-table"]')
|
||||
.find('[data-test="schema-stream-_timestamp-field-fts-key-checkbox"]');
|
||||
const KubHashCheckbox = wrapper
|
||||
.find('[data-test="schema-log-stream-field-mapping-table"]')
|
||||
.find("tbody")
|
||||
.find(
|
||||
'[data-test="schema-stream-kubernetes.container_hash-field-fts-key-checkbox"]',
|
||||
);
|
||||
expect(
|
||||
timeStampCheckbox.find(".q-checkbox__inner--truthy").exists(),
|
||||
).toBeFalsy();
|
||||
expect(
|
||||
KubHashCheckbox.find(".q-checkbox__inner--truthy").exists(),
|
||||
).toBeFalsy();
|
||||
});
|
||||
|
||||
describe("When user make changes and update settings", () => {
|
||||
const updateStream = vi.spyOn(StreamService, "updateSettings");
|
||||
let logPartition, timeStampCheckbox, updateSettingsButton: any;
|
||||
beforeEach(async () => {
|
||||
logPartition = wrapper
|
||||
.find('[data-test="schema-log-stream-field-mapping-table"]')
|
||||
.find('[data-test="schema-stream-log-field-partition-key-checkbox"]');
|
||||
timeStampCheckbox = wrapper
|
||||
.find('[data-test="schema-log-stream-field-mapping-table"]')
|
||||
.find('[data-test="schema-stream-_timestamp-field-fts-key-checkbox"]');
|
||||
updateSettingsButton = wrapper.find(
|
||||
'[data-test="schema-update-settings-button"]',
|
||||
);
|
||||
|
||||
await logPartition.trigger("click");
|
||||
await timeStampCheckbox.trigger("click");
|
||||
});
|
||||
|
||||
it("Should make api call to save updated settings", async () => {
|
||||
global.server.use(
|
||||
rest.post(
|
||||
`${store.state.API_ENDPOINT}/api/${store.state.selectedOrganization.identifier}/k8s_json/settings`,
|
||||
(req: any, res: any, ctx: any) => {
|
||||
return res(ctx.status(200), ctx.json({ code: 200 }));
|
||||
},
|
||||
),
|
||||
);
|
||||
await updateSettingsButton.trigger("submit");
|
||||
expect(updateStream).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,176 @@
|
||||
// Copyright 2023 OpenObserve Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { http, HttpResponse } from "msw";
|
||||
import { associate_members } from "../mockData/mockAssociateMembers";
|
||||
import streams from "../mockData/streams";
|
||||
import users from "../mockData/users";
|
||||
import alerts from "../mockData/alerts";
|
||||
import logs from "../mockData/logs";
|
||||
import organizations from "../mockData/organizations";
|
||||
import home from "../mockData/home";
|
||||
import store from "./store";
|
||||
|
||||
// TODO OK: Move below rest handlers to separate file
|
||||
export const restHandlers = [
|
||||
http.get(
|
||||
`${store.state.API_ENDPOINT}/api/organizations/associated_members/${store.state.selectedOrganization.identifier}`,
|
||||
({ request }) => {
|
||||
return HttpResponse.json(associate_members);
|
||||
},
|
||||
),
|
||||
|
||||
http.get(
|
||||
`${store.state.API_ENDPOINT}/api/${store.state.selectedOrganization.identifier}/functions?page_num=1&page_size=100000&sort_by=name&desc=false&name=`,
|
||||
({ request }) => {
|
||||
return HttpResponse.json({
|
||||
list: [
|
||||
{
|
||||
function: ".a=123 \n .",
|
||||
name: "lskjf",
|
||||
params: "row",
|
||||
numArgs: 1,
|
||||
transType: 0,
|
||||
},
|
||||
{
|
||||
function: ".a=123 \n .",
|
||||
name: "nginx_function",
|
||||
params: "row",
|
||||
numArgs: 1,
|
||||
transType: 0,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
),
|
||||
|
||||
http.post(
|
||||
`${store.state.API_ENDPOINT}/api/${store.state.selectedOrganization.identifier}/k8s_json/alerts/?type=logs`,
|
||||
() => {
|
||||
return HttpResponse.json({});
|
||||
},
|
||||
),
|
||||
|
||||
http.get(
|
||||
`${store.state.API_ENDPOINT}/api/${store.state.selectedOrganization.identifier}/streams`,
|
||||
({ request }) => {
|
||||
return HttpResponse.json(streams.stream_list);
|
||||
},
|
||||
),
|
||||
|
||||
http.get(
|
||||
`${store.state.API_ENDPOINT}/api/${store.state.selectedOrganization.identifier}/k8s_json/schema`,
|
||||
({ request }) => {
|
||||
return HttpResponse.json(streams.stream_details);
|
||||
},
|
||||
),
|
||||
|
||||
http.get(
|
||||
`${store.state.API_ENDPOINT}/api/${store.state.selectedOrganization.identifier}/org_users`,
|
||||
({ request }) => {
|
||||
return HttpResponse.json(users.org_users);
|
||||
},
|
||||
),
|
||||
|
||||
http.get(
|
||||
`${store.state.API_ENDPOINT}/api/${store.state.selectedOrganization.identifier}/users`,
|
||||
({ request }) => {
|
||||
return HttpResponse.json(users.users);
|
||||
},
|
||||
),
|
||||
|
||||
http.get(
|
||||
`${store.state.API_ENDPOINT}/api/${store.state.selectedOrganization.identifier}/alerts`,
|
||||
({ request }) => {
|
||||
return HttpResponse.json(alerts.alerts.get);
|
||||
},
|
||||
),
|
||||
|
||||
http.get(
|
||||
`${store.state.API_ENDPOINT}/api/${store.state.selectedOrganization.identifier}/alerts/templates`,
|
||||
({ request }) => {
|
||||
return HttpResponse.json(alerts.templates.get);
|
||||
},
|
||||
),
|
||||
|
||||
http.get(
|
||||
`${store.state.API_ENDPOINT}/api/${store.state.selectedOrganization.identifier}/alerts/destinations`,
|
||||
({ request }) => {
|
||||
return HttpResponse.json(alerts.destinations.get);
|
||||
},
|
||||
),
|
||||
|
||||
http.post(
|
||||
`${store.state.API_ENDPOINT}/api/${store.state.selectedOrganization.identifier}/_search`,
|
||||
({ request }) => {
|
||||
return HttpResponse.json(logs.search);
|
||||
},
|
||||
),
|
||||
|
||||
http.get(
|
||||
`${store.state.API_ENDPOINT}/api/${store.state.selectedOrganization.identifier}/organizations`,
|
||||
({ request }) => {
|
||||
return HttpResponse.json(organizations.list);
|
||||
},
|
||||
),
|
||||
|
||||
http.get(
|
||||
`${store.state.API_ENDPOINT}/api/${store.state.selectedOrganization.identifier}/summary`,
|
||||
({ request }) => {
|
||||
return HttpResponse.json(home.summary.get);
|
||||
},
|
||||
),
|
||||
|
||||
http.get(`${store.state.API_ENDPOINT}/config`, ({ request }) => {
|
||||
return HttpResponse.json({
|
||||
version: "v0.3.2",
|
||||
instance: "7049348417797095424",
|
||||
commit_hash: "3cc381d699e28bcb1b6d74310be16ec060b37e0d",
|
||||
build_date: "2023-04-05T11:01:23Z",
|
||||
default_fts_keys: ["log", "message", "msg", "content", "data"],
|
||||
telemetry_enabled: true,
|
||||
default_functions: [
|
||||
{
|
||||
name: "match_all_raw",
|
||||
text: "match_all_raw('v')",
|
||||
},
|
||||
{
|
||||
name: "match_all_raw_ignore_case",
|
||||
text: "match_all_raw_ignore_case('v')",
|
||||
},
|
||||
{
|
||||
name: "match_all",
|
||||
text: "match_all('v')",
|
||||
},
|
||||
{
|
||||
name: "str_match",
|
||||
text: "str_match(field, 'v')",
|
||||
},
|
||||
{
|
||||
name: "str_match_ignore_case",
|
||||
text: "str_match_ignore_case(field, 'v')",
|
||||
},
|
||||
{
|
||||
name: "re_match",
|
||||
text: "re_match(field, 'pattern')",
|
||||
},
|
||||
{
|
||||
name: "re_not_match",
|
||||
text: "re_not_match(field, 'pattern')",
|
||||
},
|
||||
],
|
||||
});
|
||||
}),
|
||||
];
|
||||
@@ -1 +1,16 @@
|
||||
// Copyright 2023 OpenObserve Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
export * from "./install-quasar-plugin";
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
// Copyright 2023 OpenObserve Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { config } from "@vue/test-utils";
|
||||
import { cloneDeep } from "lodash-es";
|
||||
import { Quasar } from "quasar";
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
// Copyright 2023 OpenObserve Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Injections for Components with a QPage root Element
|
||||
*/
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
// Copyright 2023 OpenObserve Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { config } from "@vue/test-utils";
|
||||
|
||||
// locally defined plugin, see "Writing a Plugin"
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
// Copyright 2023 OpenObserve Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import router from "@/router/routes";
|
||||
|
||||
// interface RouterMap {
|
||||
|
||||
@@ -1,132 +1,27 @@
|
||||
import { beforeAll, afterEach, afterAll, vi } from "vitest";
|
||||
// Copyright 2023 OpenObserve Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// @ts-ignore
|
||||
import { http, HttpResponse } from "msw";
|
||||
import { beforeAll, afterEach, afterAll, vi } from "vitest";
|
||||
|
||||
import { setupServer } from "msw/node";
|
||||
import { associate_members } from "../mockData/mockAssociateMembers";
|
||||
import streams from "@/test/unit/mockData/streams";
|
||||
import users from "../mockData/users";
|
||||
import alerts from "../mockData/alerts";
|
||||
import logs from "../mockData/logs";
|
||||
import organizations from "../mockData/organizations";
|
||||
import "whatwg-fetch";
|
||||
import store from "./store";
|
||||
|
||||
import "../../__mocks__/index";
|
||||
import home from "../mockData/home";
|
||||
|
||||
import.meta.env.VITE_OPENOBSERVE_ENDPOINT = "http://localhost:8080";
|
||||
import { restHandlers } from "./handlers";
|
||||
|
||||
// TODO OK: Move below rest handlers to separate file
|
||||
export const restHandlers = [
|
||||
http.get(
|
||||
`${store.state.API_ENDPOINT}/api/organizations/associated_members/${store.state.selectedOrganization.identifier}`,
|
||||
({ request }) => {
|
||||
return HttpResponse.json(associate_members);
|
||||
},
|
||||
),
|
||||
|
||||
http.get(
|
||||
`${store.state.API_ENDPOINT}/api/${store.state.selectedOrganization.identifier}/streams`,
|
||||
({ request }) => {
|
||||
return HttpResponse.json(streams.stream_list);
|
||||
},
|
||||
),
|
||||
|
||||
http.get(
|
||||
`${store.state.API_ENDPOINT}/api/${store.state.selectedOrganization.identifier}/k8s_json/schema`,
|
||||
({ request }) => {
|
||||
return HttpResponse.json(streams.stream_details);
|
||||
},
|
||||
),
|
||||
|
||||
http.get(
|
||||
`${store.state.API_ENDPOINT}/api/${store.state.selectedOrganization.identifier}/org_users`,
|
||||
({ request }) => {
|
||||
return HttpResponse.json(users.org_users);
|
||||
},
|
||||
),
|
||||
|
||||
http.get(
|
||||
`${store.state.API_ENDPOINT}/api/${store.state.selectedOrganization.identifier}/users`,
|
||||
({ request }) => {
|
||||
return HttpResponse.json(users.users);
|
||||
},
|
||||
),
|
||||
|
||||
http.get(
|
||||
`${store.state.API_ENDPOINT}/api/${store.state.selectedOrganization.identifier}/alerts`,
|
||||
({ request }) => {
|
||||
return HttpResponse.json(alerts.alerts.get);
|
||||
},
|
||||
),
|
||||
|
||||
http.get(
|
||||
`${store.state.API_ENDPOINT}/api/${store.state.selectedOrganization.identifier}/alerts/templates`,
|
||||
({ request }) => {
|
||||
return HttpResponse.json(alerts.templates.get);
|
||||
},
|
||||
),
|
||||
|
||||
http.get(
|
||||
`${store.state.API_ENDPOINT}/api/${store.state.selectedOrganization.identifier}/alerts/destinations`,
|
||||
({ request }) => {
|
||||
return HttpResponse.json(alerts.destinations.get);
|
||||
},
|
||||
),
|
||||
|
||||
http.post(
|
||||
`${store.state.API_ENDPOINT}/api/${store.state.selectedOrganization.identifier}/_search`,
|
||||
({ request }) => {
|
||||
return HttpResponse.json(logs.search);
|
||||
},
|
||||
),
|
||||
|
||||
http.get(
|
||||
`${store.state.API_ENDPOINT}/api/${store.state.selectedOrganization.identifier}/organizations`,
|
||||
({ request }) => {
|
||||
return HttpResponse.json(organizations.list);
|
||||
},
|
||||
),
|
||||
|
||||
http.get(
|
||||
`${store.state.API_ENDPOINT}/api/${store.state.selectedOrganization.identifier}/summary`,
|
||||
({ request }) => {
|
||||
return HttpResponse.json(home.summary.get);
|
||||
},
|
||||
),
|
||||
|
||||
http.get(`${store.state.API_ENDPOINT}/config`, ({ request }) => {
|
||||
return HttpResponse.json({
|
||||
version: "v0.3.2",
|
||||
instance: "7049348417797095424",
|
||||
commit_hash: "3cc381d699e28bcb1b6d74310be16ec060b37e0d",
|
||||
build_date: "2023-04-05T11:01:23Z",
|
||||
default_fts_keys: ["log", "message", "msg", "content", "data"],
|
||||
telemetry_enabled: true,
|
||||
default_functions: [
|
||||
{
|
||||
name: "match_all",
|
||||
text: "match_all('v')",
|
||||
},
|
||||
{
|
||||
name: "str_match",
|
||||
text: "str_match(field, 'v')",
|
||||
},
|
||||
{
|
||||
name: "str_match_ignore_case",
|
||||
text: "str_match_ignore_case(field, 'v')",
|
||||
},
|
||||
{
|
||||
name: "re_match",
|
||||
text: "re_match(field, 'pattern')",
|
||||
},
|
||||
{
|
||||
name: "re_not_match",
|
||||
text: "re_not_match(field, 'pattern')",
|
||||
},
|
||||
],
|
||||
});
|
||||
}),
|
||||
];
|
||||
|
||||
const server = setupServer(...restHandlers);
|
||||
|
||||
@@ -137,16 +32,42 @@ const server = setupServer(...restHandlers);
|
||||
declare global {
|
||||
// eslint-disable-next-line no-var
|
||||
var server: any;
|
||||
// eslint-disable-next-line no-var
|
||||
var IntersectionObserver: {
|
||||
new (callback: IntersectionObserverCallback, options?: IntersectionObserverInit): IntersectionObserver;
|
||||
prototype: IntersectionObserver;
|
||||
};
|
||||
}
|
||||
|
||||
class MockIntersectionObserver implements IntersectionObserver {
|
||||
readonly root: Element | null = null;
|
||||
readonly rootMargin: string = '';
|
||||
readonly thresholds: ReadonlyArray<number> = [];
|
||||
|
||||
constructor(
|
||||
private callback: IntersectionObserverCallback,
|
||||
private options?: IntersectionObserverInit
|
||||
) {}
|
||||
|
||||
observe = vi.fn();
|
||||
unobserve = vi.fn();
|
||||
disconnect = vi.fn();
|
||||
takeRecords = vi.fn().mockReturnValue([]);
|
||||
}
|
||||
|
||||
// Assign the mock to the global object
|
||||
global.IntersectionObserver = MockIntersectionObserver;
|
||||
|
||||
vi.stubGlobal("server", server);
|
||||
|
||||
// Start server before all tests
|
||||
beforeAll(() => server.listen({ onUnhandledRequest: "error" }));
|
||||
global.document.queryCommandSupported = vi.fn().mockReturnValue(true);
|
||||
|
||||
// Close server after all tests
|
||||
beforeAll(() => server.listen())
|
||||
|
||||
// Reset any request handlers after each test (for test isolation)
|
||||
afterEach(() => server.resetHandlers())
|
||||
|
||||
// Stop the server when tests are done
|
||||
afterAll(() => {
|
||||
server.close();
|
||||
});
|
||||
|
||||
// Reset handlers after each test `important for test isolation`
|
||||
afterEach(() => server.resetHandlers());
|
||||
server.close();
|
||||
})
|
||||
|
||||
@@ -1,12 +1,27 @@
|
||||
// Copyright 2023 OpenObserve Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { createStore } from "vuex";
|
||||
|
||||
const store = createStore({
|
||||
state: {
|
||||
API_ENDPOINT: "http://localhost:8080",
|
||||
API_ENDPOINT: "http://localhost:5080",
|
||||
selectedOrganization: {
|
||||
label: "default Organization",
|
||||
id: 159,
|
||||
identifier: "default_organization_01",
|
||||
identifier: "default",
|
||||
user_email: "example@gmail.com",
|
||||
subscription_type: "",
|
||||
},
|
||||
@@ -33,6 +48,9 @@ const store = createStore({
|
||||
build_date: "2023-03-11T03:55:28Z",
|
||||
default_fts_keys: ["log", "message", "msg", "content", "data"],
|
||||
show_stream_stats_doc_num: true,
|
||||
data_retention_days: true,
|
||||
extended_data_retention_days: 45,
|
||||
user_defined_schemas_enabled: true,
|
||||
default_functions: [
|
||||
{
|
||||
name: "match_all",
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
// Copyright 2023 OpenObserve Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
export const organizations = {
|
||||
data: [
|
||||
{
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
// Copyright 2023 OpenObserve Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
export default {
|
||||
alerts: {
|
||||
get: {
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
// Copyright 2023 OpenObserve Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
export default {
|
||||
summary: {
|
||||
get: {
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
// Copyright 2023 OpenObserve Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
export default {
|
||||
search: {
|
||||
took: 75,
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
// Copyright 2023 OpenObserve Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
export const associate_members = {
|
||||
"data": [
|
||||
{
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
// Copyright 2023 OpenObserve Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
export default {
|
||||
list: {
|
||||
data: [
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
// Copyright 2023 OpenObserve Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
export default {
|
||||
stream_list: {
|
||||
list: [
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
// Copyright 2023 OpenObserve Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
export default {
|
||||
org_users: {
|
||||
data: [
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
// Vitest Snapshot v1
|
||||
|
||||
exports[`Alert List > Should render json when user clicks on json tab 1`] = `
|
||||
"{
|
||||
\\"_timestamp\\": \\"1680246906650420\\",
|
||||
\\"kubernetes_container_name\\": \\"ziox\\",
|
||||
\\"kubernetes_container_hash\\": \\"058694856476.dkr.ecr.us-west-2.amazonaws.com/ziox@sha256:3dbbb0dc1eab2d5a3b3e4a75fd87d194e8095c92d7b2b62e7cdbd07020f54589\\"
|
||||
}"
|
||||
`;
|
||||
@@ -1,42 +0,0 @@
|
||||
// Vitest Snapshot v1
|
||||
|
||||
exports[`Search Result > Should render the q-virtual-scroll component with the correct props and call the 'onScroll' method when the 'virtual-scroll' event is emitted 1`] = `
|
||||
"<div class=\\"q-markup-table q-table__container q-table__card q-table--horizontal-separator q-table--no-wrap q-virtual-scroll q-virtual-scroll--vertical scroll\\" data-test=\\"logs-search-result-logs-table\\" id=\\"searchGridComponent\\" tabindex=\\"0\\" data-v-ae03aa38=\\"\\" style=\\"height: calc(100vh - 0px);\\">
|
||||
<table class=\\"q-table\\">
|
||||
<thead class=\\"thead-sticky text-left\\" data-v-ae03aa38=\\"\\">
|
||||
<tr data-v-ae03aa38=\\"\\">
|
||||
<th class=\\"table-header\\" data-v-ae03aa38=\\"\\"><span class=\\"table-head-label\\" data-v-ae03aa38=\\"\\">timestamp</span></th>
|
||||
<th class=\\"table-header\\" data-v-ae03aa38=\\"\\"><span class=\\"table-head-label\\" data-v-ae03aa38=\\"\\">source</span></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class=\\"q-virtual-scroll__padding\\">
|
||||
<tr>
|
||||
<td style=\\"height: 0px; --q-virtual-scroll-item-height: 25px;\\" colspan=\\"100\\"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tbody class=\\"q-virtual-scroll__content\\" tabindex=\\"-1\\">
|
||||
<tr class=\\"q-tr\\" data-test=\\"logs-search-result-detail-1680246906644637\\" style=\\"cursor: pointer;\\" data-v-ae03aa38=\\"\\">
|
||||
<td class=\\"q-td \\" data-v-ae03aa38=\\"\\">
|
||||
<div data-v-ae03aa38=\\"\\"><span iskeyword=\\"false\\" text=\\"Mar 31, 2023 12:45:06.644 +05:30\\"><span title=\\"\\">Mar 31, 2023 12:45:06.644 +05:30</span></span></div>
|
||||
</td>
|
||||
<td class=\\"q-td \\" data-v-ae03aa38=\\"\\">
|
||||
<div data-v-ae03aa38=\\"\\"><span iskeyword=\\"false\\" text=\\"{"_timestamp":1680246906644637,"kubernetes_annotations_kubernetes_io_psp":"eks.privileged","kubernetes_container_hash":"058694856476.dkr.ecr.us-west-2.amazonaws.com/ziox@sha256:3dbbb0dc1eab2d5a3b3e4a75fd87d194e8095c92d7b2b62e7cdbd07020f54589","kubernetes_container_image":"058694856476.dkr.ecr.us-west-2.amazonaws.com/ziox:v0.0.3","kubernetes_container_name":"ziox","kubernetes_docker_id":"56510ea4003f201fa7913c18d7c8dc639c576e5d1c4bbf0ead911d2d68ae8f31","kubernetes_host":"ip-10-2-56-221.us-east-2.compute.internal","kubernetes_labels_app":"ziox","kubernetes_labels_name":"ziox-querier","kubernetes_labels_pod_template_hash":"595748494c","kubernetes_labels_role":"querier","kubernetes_namespace_name":"ziox","kubernetes_pod_id":"810e7dbc-fb09-4a8f-9108-6b8785754af9","kubernetes_pod_name":"ziox-querier-595748494c-7xqlg","log":"[2022-12-27T14:12:29Z INFO zinc_enl::service::search::datafusion] search file: Bhargav_organization_29/logs/default/2022/12/23/12/7012038228660338688.parquet, need add columns: [\\\\"from\\\\"]","stream":"stderr"}\\"><span title=\\"\\">{\\"_timestamp\\":1680246906644637,\\"kubernetes_annotations_kubernetes_io_psp\\":\\"eks.privileged\\",\\"kubernetes_container_hash\\":\\"058694856476.dkr.ecr.us-west-2.amazonaws.com/ziox@sha256:3dbbb0dc1eab2d5a3b3e4a75fd87d194e8095c92d7b2b62e7cdbd07020f54589\\",\\"kubernetes_container_image\\":\\"058694856476.dkr.ecr.us-west-2.amazonaws.com/ziox:v0.0.3\\",\\"kubernetes_container_name\\":\\"ziox\\",\\"kubernetes_docker_id\\":\\"56510ea4003f201fa7913c18d7c8dc639c576e5d1c4bbf0ead911d2d68ae8f31\\",\\"kubernetes_host\\":\\"ip-10-2-56-221.us-east-2.compute.internal\\",\\"kubernetes_labels_app\\":\\"ziox\\",\\"kubernetes_labels_name\\":\\"ziox-querier\\",\\"kubernetes_labels_pod_template_hash\\":\\"595748494c\\",\\"kubernetes_labels_role\\":\\"querier\\",\\"kubernetes_namespace_name\\":\\"ziox\\",\\"kubernetes_pod_id\\":\\"810e7dbc-fb09-4a8f-9108-6b8785754af9\\",\\"kubernetes_pod_name\\":\\"ziox-querier-595748494c-7xqlg\\",\\"log\\":\\"[2022-12-27T14:12:29Z INFO zinc_enl::service::search::datafusion] search file: Bhargav_organization_29/logs/default/2022/12/23/12/7012038228660338688.parquet, need add columns: [\\\\\\"from\\\\\\"]\\",\\"stream\\":\\"stderr\\"}</span></span></div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class=\\"q-tr\\" data-test=\\"logs-search-result-detail-1680246906644599\\" style=\\"cursor: pointer;\\" data-v-ae03aa38=\\"\\">
|
||||
<td class=\\"q-td \\" data-v-ae03aa38=\\"\\">
|
||||
<div data-v-ae03aa38=\\"\\"><span iskeyword=\\"false\\" text=\\"Mar 31, 2023 12:45:06.644 +05:30\\"><span title=\\"\\">Mar 31, 2023 12:45:06.644 +05:30</span></span></div>
|
||||
</td>
|
||||
<td class=\\"q-td \\" data-v-ae03aa38=\\"\\">
|
||||
<div data-v-ae03aa38=\\"\\"><span iskeyword=\\"false\\" text=\\"{"_timestamp":1680246906644599,"kubernetes_annotations_kubernetes_io_psp":"eks.privileged","kubernetes_container_hash":"058694856476.dkr.ecr.us-west-2.amazonaws.com/ziox@sha256:3dbbb0dc1eab2d5a3b3e4a75fd87d194e8095c92d7b2b62e7cdbd07020f54589","kubernetes_container_image":"058694856476.dkr.ecr.us-west-2.amazonaws.com/ziox:v0.0.3","kubernetes_container_name":"ziox","kubernetes_docker_id":"56510ea4003f201fa7913c18d7c8dc639c576e5d1c4bbf0ead911d2d68ae8f31","kubernetes_host":"ip-10-2-56-221.us-east-2.compute.internal","kubernetes_labels_app":"ziox","kubernetes_labels_name":"ziox-querier","kubernetes_labels_pod_template_hash":"595748494c","kubernetes_labels_role":"querier","kubernetes_namespace_name":"ziox","kubernetes_pod_id":"810e7dbc-fb09-4a8f-9108-6b8785754af9","kubernetes_pod_name":"ziox-querier-595748494c-7xqlg","log":"[2022-12-27T14:12:29Z INFO aws_config::default_provider::credentials] provide_credentials; provider=default_chain","stream":"stderr"}\\"><span title=\\"\\">{\\"_timestamp\\":1680246906644599,\\"kubernetes_annotations_kubernetes_io_psp\\":\\"eks.privileged\\",\\"kubernetes_container_hash\\":\\"058694856476.dkr.ecr.us-west-2.amazonaws.com/ziox@sha256:3dbbb0dc1eab2d5a3b3e4a75fd87d194e8095c92d7b2b62e7cdbd07020f54589\\",\\"kubernetes_container_image\\":\\"058694856476.dkr.ecr.us-west-2.amazonaws.com/ziox:v0.0.3\\",\\"kubernetes_container_name\\":\\"ziox\\",\\"kubernetes_docker_id\\":\\"56510ea4003f201fa7913c18d7c8dc639c576e5d1c4bbf0ead911d2d68ae8f31\\",\\"kubernetes_host\\":\\"ip-10-2-56-221.us-east-2.compute.internal\\",\\"kubernetes_labels_app\\":\\"ziox\\",\\"kubernetes_labels_name\\":\\"ziox-querier\\",\\"kubernetes_labels_pod_template_hash\\":\\"595748494c\\",\\"kubernetes_labels_role\\":\\"querier\\",\\"kubernetes_namespace_name\\":\\"ziox\\",\\"kubernetes_pod_id\\":\\"810e7dbc-fb09-4a8f-9108-6b8785754af9\\",\\"kubernetes_pod_name\\":\\"ziox-querier-595748494c-7xqlg\\",\\"log\\":\\"[2022-12-27T14:12:29Z INFO aws_config::default_provider::credentials] provide_credentials; provider=default_chain\\",\\"stream\\":\\"stderr\\"}</span></span></div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tbody class=\\"q-virtual-scroll__padding\\">
|
||||
<tr>
|
||||
<td style=\\"height: 0px; --q-virtual-scroll-item-height: 25px;\\" colspan=\\"100\\"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>"
|
||||
`;
|
||||
@@ -1,35 +0,0 @@
|
||||
import { mount } from "@vue/test-utils";
|
||||
import About from "../../../views/About.vue";
|
||||
import { Quasar, Dialog, Notify } from "quasar";
|
||||
import { expect, it } from "vitest";
|
||||
import i18n from "../../../locales";
|
||||
import { createStore } from "vuex";
|
||||
import { installQuasar } from "../helpers/install-quasar-plugin";
|
||||
|
||||
installQuasar();
|
||||
const store = createStore({
|
||||
state: {
|
||||
zoConfig: {
|
||||
version: "1",
|
||||
commit_hash: "test",
|
||||
build_date: "01-01-23",
|
||||
},
|
||||
API_ENDPOINT: "test",
|
||||
},
|
||||
});
|
||||
it("should mount About view", async () => {
|
||||
const wrapper = mount(About, {
|
||||
shallow: false,
|
||||
components: {
|
||||
Notify,
|
||||
Dialog,
|
||||
},
|
||||
global: {
|
||||
plugins: [i18n],
|
||||
provide: {
|
||||
store: store,
|
||||
},
|
||||
},
|
||||
});
|
||||
expect(About).toBeTruthy();
|
||||
});
|
||||
@@ -1,28 +0,0 @@
|
||||
// Vitest Snapshot v1
|
||||
|
||||
exports[`Streams > Should match previous table snapshot 1`] = `
|
||||
"<table class=\\"q-table\\">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class=\\"text-left\\">#</th>
|
||||
<th class=\\"text-left sortable\\">Name<i class=\\"q-icon notranslate material-icons q-table__sort-icon q-table__sort-icon--left\\" aria-hidden=\\"true\\" role=\\"presentation\\">arrow_upward</i></th>
|
||||
<th class=\\"text-left sortable\\">Type<i class=\\"q-icon notranslate material-icons q-table__sort-icon q-table__sort-icon--left\\" aria-hidden=\\"true\\" role=\\"presentation\\">arrow_upward</i></th>
|
||||
<th class=\\"text-left sortable\\">Doc Num<i class=\\"q-icon notranslate material-icons q-table__sort-icon q-table__sort-icon--left\\" aria-hidden=\\"true\\" role=\\"presentation\\">arrow_upward</i></th>
|
||||
<th class=\\"text-left sortable\\">Ingested Data<i class=\\"q-icon notranslate material-icons q-table__sort-icon q-table__sort-icon--left\\" aria-hidden=\\"true\\" role=\\"presentation\\">arrow_upward</i></th>
|
||||
<th class=\\"text-left sortable\\">Compressed Size<i class=\\"q-icon notranslate material-icons q-table__sort-icon q-table__sort-icon--left\\" aria-hidden=\\"true\\" role=\\"presentation\\">arrow_upward</i></th>
|
||||
<th class=\\"text-center\\">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class=\\"\\">
|
||||
<td class=\\"text-left\\">01</td>
|
||||
<td class=\\"text-left\\">k8s_json</td>
|
||||
<td class=\\"text-left\\">logs</td>
|
||||
<td class=\\"text-left\\">400</td>
|
||||
<td class=\\"text-left\\">0.74 MB</td>
|
||||
<td class=\\"text-left\\">0.03 MB</td>
|
||||
<td class=\\"q-td text-center\\"><button class=\\"q-btn q-btn-item non-selectable no-outline q-btn--flat q-btn--round q-btn--actionable q-focusable q-hoverable q-ml-xs iconHoverBtn\\" style=\\"font-size: 10px; padding: 8px; min-width: 0; min-height: 0;\\" tabindex=\\"0\\" type=\\"button\\" title=\\"Delete\\"><span class=\\"q-focus-helper\\"></span><span class=\\"q-btn__content text-center col items-center q-anchor--skip justify-center row\\"><span class=\\"q-icon\\" aria-hidden=\\"true\\" role=\\"img\\"><img src=\\"/src/assets/images/common/delete_icon.svg\\"></span></span></button><button class=\\"q-btn q-btn-item non-selectable no-outline q-btn--flat q-btn--round q-btn--actionable q-focusable q-hoverable q-ml-xs iconHoverBtn\\" style=\\"font-size: 10px; padding: 8px; min-width: 0; min-height: 0;\\" tabindex=\\"0\\" type=\\"button\\" title=\\"Stream Detail\\"><span class=\\"q-focus-helper\\"></span><span class=\\"q-btn__content text-center col items-center q-anchor--skip justify-center row\\"><span class=\\"q-icon\\" aria-hidden=\\"true\\" role=\\"img\\"><img src=\\"/src/assets/images/common/list_icon.svg\\"></span></span></button></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>"
|
||||
`;
|
||||
+12
-11
@@ -22,7 +22,6 @@ import { useStore } from "vuex";
|
||||
import useStreams from "@/composables/useStreams";
|
||||
import userService from "@/services/users";
|
||||
import { DateTime as _DateTime } from "luxon";
|
||||
import store from "../stores";
|
||||
import cronParser from "cron-parser";
|
||||
|
||||
let moment: any;
|
||||
@@ -965,32 +964,34 @@ export const deepCopy = (value: any) => {
|
||||
return JSON.parse(JSON.stringify(value));
|
||||
};
|
||||
|
||||
export const getWebSocketUrl = (request_id: string, org_identifier: string) => {
|
||||
export const getWebSocketUrl = (
|
||||
request_id: string,
|
||||
org_identifier: string,
|
||||
apiEndPoint: string,
|
||||
) => {
|
||||
const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
|
||||
return `${protocol}//${store.state.API_ENDPOINT.split("//")[1]}/api/${org_identifier}/ws/v2/${request_id}`;
|
||||
return `${protocol}//${apiEndPoint.split("//")[1]}/api/${org_identifier}/ws/v2/${request_id}`;
|
||||
};
|
||||
|
||||
export const isWebSocketEnabled = () => {
|
||||
if (!store.state.zoConfig?.websocket_enabled) {
|
||||
export const isWebSocketEnabled = (data: any) => {
|
||||
if (!data.zoConfig?.websocket_enabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((window as any).use_web_socket === undefined) {
|
||||
return store?.state?.organizationData?.organizationSettings
|
||||
?.enable_websocket_search;
|
||||
return data.organizationData?.organizationSettings?.enable_websocket_search;
|
||||
} else {
|
||||
return (window as any).use_web_socket;
|
||||
}
|
||||
};
|
||||
|
||||
export const isStreamingEnabled = () => {
|
||||
if (!store.state.zoConfig?.streaming_enabled) {
|
||||
export const isStreamingEnabled = (data: any) => {
|
||||
if (!data.zoConfig?.streaming_enabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((window as any).use_streaming === undefined) {
|
||||
return store?.state?.organizationData?.organizationSettings
|
||||
?.enable_streaming_search;
|
||||
return data.organizationData?.organizationSettings?.enable_streaming_search;
|
||||
} else {
|
||||
return (window as any).use_streaming;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
// Copyright 2023 OpenObserve Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { mount } from "@vue/test-utils";
|
||||
import About from "@/views/About.vue";
|
||||
import { Quasar, Dialog, Notify } from "quasar";
|
||||
import { expect, it } from "vitest";
|
||||
import i18n from "@/locales";
|
||||
import { createStore } from "vuex";
|
||||
import { installQuasar } from "@/test/unit/helpers/install-quasar-plugin";
|
||||
|
||||
installQuasar();
|
||||
const store = createStore({
|
||||
state: {
|
||||
zoConfig: {
|
||||
version: "1",
|
||||
commit_hash: "test",
|
||||
build_date: "01-01-23",
|
||||
},
|
||||
API_ENDPOINT: "test",
|
||||
},
|
||||
});
|
||||
it("should mount About view", async () => {
|
||||
const wrapper = mount(About, {
|
||||
shallow: false,
|
||||
components: {
|
||||
Notify,
|
||||
Dialog,
|
||||
},
|
||||
global: {
|
||||
plugins: [i18n],
|
||||
provide: {
|
||||
store: store,
|
||||
},
|
||||
},
|
||||
});
|
||||
expect(About).toBeTruthy();
|
||||
});
|
||||
@@ -15,12 +15,12 @@
|
||||
|
||||
import { describe, expect, it, beforeEach, vi, afterEach } from "vitest";
|
||||
import { mount } from "@vue/test-utils";
|
||||
import { installQuasar } from "../helpers/install-quasar-plugin";
|
||||
import { installQuasar } from "@/test/unit/helpers/install-quasar-plugin";
|
||||
import { Dialog, Notify } from "quasar";
|
||||
import AppAlerts from "../../../views/AppAlerts.vue";
|
||||
import i18n from "../../../locales";
|
||||
import store from "../helpers/store";
|
||||
import router from "../helpers/router";
|
||||
import AppAlerts from "@/views/AppAlerts.vue";
|
||||
import i18n from "@/locales";
|
||||
import store from "@/test/unit/helpers/store";
|
||||
import router from "@/test/unit/helpers/router";
|
||||
|
||||
installQuasar({
|
||||
plugins: [Dialog, Notify],
|
||||
@@ -1,11 +1,26 @@
|
||||
// Copyright 2023 OpenObserve Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { describe, expect, it, beforeEach, vi, afterEach } from "vitest";
|
||||
import { mount, flushPromises } from "@vue/test-utils";
|
||||
import { installQuasar } from "../helpers/install-quasar-plugin";
|
||||
import { installQuasar } from "@/test/unit/helpers/install-quasar-plugin";
|
||||
import { Dialog, Notify } from "quasar";
|
||||
import LogStream from "../../../views/LogStream.vue";
|
||||
import i18n from "../../../locales";
|
||||
import store from "../helpers/store";
|
||||
import router from "../helpers/router";
|
||||
import LogStream from "@/views/LogStream.vue";
|
||||
import i18n from "@/locales";
|
||||
import store from "@/test/unit/helpers/store";
|
||||
import router from "@/test/unit/helpers/router";
|
||||
|
||||
installQuasar({
|
||||
plugins: [Dialog, Notify],
|
||||
@@ -15,14 +15,14 @@
|
||||
|
||||
import { describe, expect, it, beforeEach, vi, afterEach } from "vitest";
|
||||
import { mount, flushPromises } from "@vue/test-utils";
|
||||
import { installQuasar } from "../helpers/install-quasar-plugin";
|
||||
import { installQuasar } from "@/test/unit/helpers/install-quasar-plugin";
|
||||
import { Dialog, Notify } from "quasar";
|
||||
|
||||
import Logs from "@/views/Logs.vue";
|
||||
import i18n from "@/locales";
|
||||
import store from "../helpers/store";
|
||||
import SearchPlugin from "../helpers/logSearchPlugin";
|
||||
import router from "../helpers/router";
|
||||
import store from "@/test/unit/helpers/store";
|
||||
import SearchPlugin from "@/test/unit/helpers/logSearchPlugin";
|
||||
import router from "@/test/unit/helpers/router";
|
||||
|
||||
const node = document.createElement("div");
|
||||
node.setAttribute("id", "app");
|
||||
@@ -1,11 +1,26 @@
|
||||
// Copyright 2023 OpenObserve Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { describe, expect, it, beforeEach, vi, afterEach } from "vitest";
|
||||
import { mount, flushPromises } from "@vue/test-utils";
|
||||
import { installQuasar } from "../helpers/install-quasar-plugin";
|
||||
import { installQuasar } from "@/test/unit/helpers/install-quasar-plugin";
|
||||
import { Dialog, Notify } from "quasar";
|
||||
import User from "@/views/User.vue";
|
||||
import i18n from "@/locales";
|
||||
import store from "../helpers/store";
|
||||
import router from "../helpers/router";
|
||||
import store from "@/test/unit/helpers/store";
|
||||
import router from "@/test/unit/helpers/router";
|
||||
|
||||
installQuasar({
|
||||
plugins: [Dialog, Notify],
|
||||
@@ -0,0 +1,50 @@
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`Streams > Should match previous table snapshot 1`] = `
|
||||
"<table class="q-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="q-table--col-auto-width">
|
||||
<div data-v-d611dbca="" class="q-checkbox cursor-pointer no-outline row inline no-wrap items-center" tabindex="0" role="checkbox" aria-checked="false">
|
||||
<div class="q-checkbox__inner relative-position non-selectable q-checkbox__inner--falsy" style="font-size: 35px;" aria-hidden="true"><input class="hidden q-checkbox__native absolute q-ma-none q-pa-none" type="checkbox">
|
||||
<div class="q-checkbox__bg absolute"><svg class="q-checkbox__svg fit absolute-full" viewBox="0 0 24 24">
|
||||
<path class="q-checkbox__truthy" fill="none" d="M1.73,12.91 8.1,19.28 22.79,4.59"></path>
|
||||
<path class="q-checkbox__indet" d="M4,14H20V10H4"></path>
|
||||
</svg></div>
|
||||
</div><span class="no-outline" tabindex="-1"></span>
|
||||
</div>
|
||||
</th>
|
||||
<th class="text-left">#</th>
|
||||
<th class="text-left sortable sorted ">Name<i class="q-icon notranslate material-icons q-table__sort-icon q-table__sort-icon--left" aria-hidden="true">arrow_upward</i></th>
|
||||
<th class="text-left">Type</th>
|
||||
<th class="text-left sortable">Events<i class="q-icon notranslate material-icons q-table__sort-icon q-table__sort-icon--left" aria-hidden="true">arrow_upward</i></th>
|
||||
<th class="text-left sortable">Ingested Data<i class="q-icon notranslate material-icons q-table__sort-icon q-table__sort-icon--left" aria-hidden="true">arrow_upward</i></th>
|
||||
<th class="text-left">Compressed Size</th>
|
||||
<th class="text-left sortable">Index Size<i class="q-icon notranslate material-icons q-table__sort-icon q-table__sort-icon--left" aria-hidden="true">arrow_upward</i></th>
|
||||
<th class="text-center">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="">
|
||||
<td class="q-table--col-auto-width">
|
||||
<div data-v-d611dbca="" class="q-checkbox cursor-pointer no-outline row inline no-wrap items-center" tabindex="0" role="checkbox" aria-checked="false">
|
||||
<div class="q-checkbox__inner relative-position non-selectable q-checkbox__inner--falsy" style="font-size: 35px;" aria-hidden="true"><input class="hidden q-checkbox__native absolute q-ma-none q-pa-none" type="checkbox">
|
||||
<div class="q-checkbox__bg absolute"><svg class="q-checkbox__svg fit absolute-full" viewBox="0 0 24 24">
|
||||
<path class="q-checkbox__truthy" fill="none" d="M1.73,12.91 8.1,19.28 22.79,4.59"></path>
|
||||
<path class="q-checkbox__indet" d="M4,14H20V10H4"></path>
|
||||
</svg></div>
|
||||
</div><span class="no-outline" tabindex="-1"></span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="text-left">01</td>
|
||||
<td class="text-left">k8s_json</td>
|
||||
<td class="text-left">logs</td>
|
||||
<td class="text-left">400</td>
|
||||
<td class="text-left">0.74 MB</td>
|
||||
<td class="text-left">0.03 MB</td>
|
||||
<td class="text-left">NaN MB</td>
|
||||
<td data-v-d611dbca="" class="q-td text-center"><button data-v-d611dbca="" class="q-btn q-btn-item non-selectable no-outline q-btn--flat q-btn--round q-btn--actionable q-focusable q-hoverable q-ml-xs" style="font-size: 10px; padding: 8px; min-width: 0; min-height: 0;" tabindex="0" type="button" title="Explore"><span class="q-focus-helper"></span><span class="q-btn__content text-center col items-center q-anchor--skip justify-center row"><i class="q-icon notranslate material-icons" aria-hidden="true" role="img">search</i></span></button><button data-v-d611dbca="" class="q-btn q-btn-item non-selectable no-outline q-btn--flat q-btn--round q-btn--actionable q-focusable q-hoverable q-ml-xs" style="font-size: 10px; padding: 8px; min-width: 0; min-height: 0;" tabindex="0" type="button" title="Stream Detail"><span class="q-focus-helper"></span><span class="q-btn__content text-center col items-center q-anchor--skip justify-center row"><i class="q-icon notranslate material-icons" aria-hidden="true" role="img">list_alt</i></span></button><button data-v-d611dbca="" class="q-btn q-btn-item non-selectable no-outline q-btn--flat q-btn--round q-btn--actionable q-focusable q-hoverable q-ml-xs" style="font-size: 10px; padding: 8px; min-width: 0; min-height: 0;" tabindex="0" type="button" title="Delete"><span class="q-focus-helper"></span><span class="q-btn__content text-center col items-center q-anchor--skip justify-center row"><i class="q-icon" aria-hidden="true" role="img"><svg viewBox="0 0 24 24"><path style="fill: none;" d="M0 0h24v24H0V0z"></path><path d="M16 9v10H8V9h8m-1.5-6h-5l-1 1H5v2h14V4h-3.5l-1-1zM18 7H6v12c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7z"></path></svg></i></span></button></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>"
|
||||
`;
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"include": ["env.d.ts", "src/**/*", "src/**/*.vue", "src/**/*.ts", "src/**/*.tsx"],
|
||||
"exclude": ["src/**/__tests__/*", "node_modules", "dist"],
|
||||
"include": ["env.d.ts", "src/**/*", "src/**/*.vue", "src/**/*.{ts,tsx,js}"],
|
||||
"exclude": ["src/**/__tests__/*", "node_modules", "dist", "src/**/*.spec.{ts,js}"],
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"baseUrl": ".",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"references": [{ "path": "./tsconfig.node.json" }],
|
||||
"include": ["src/**/*.ts", "vite.config.*", "vitest.config.*", "cypress.config.*"],
|
||||
"include": ["vite.config.*", "vitest.config.*", "cypress.config.*"],
|
||||
"exclude": ["node_modules", "dist"],
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"extends": "./tsconfig.app.json",
|
||||
"exclude": [],
|
||||
"include": ["src/**/*.spec.{ts,js}", "vitest.config.*"],
|
||||
"exclude": ["node_modules", "dist"],
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"target": "esnext",
|
||||
@@ -19,5 +20,8 @@
|
||||
"types": ["node"],
|
||||
"baseUrl": ".",
|
||||
"downlevelIteration": true,
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
-50
@@ -21,11 +21,11 @@ import vueJsx from "@vitejs/plugin-vue-jsx";
|
||||
import { quasar, transformAssetUrls } from "@quasar/vite-plugin";
|
||||
import nodePolyfills from "rollup-plugin-node-polyfills";
|
||||
import { NodeGlobalsPolyfillPlugin } from "@esbuild-plugins/node-globals-polyfill";
|
||||
import path from "path";
|
||||
import dotenv from "dotenv";
|
||||
import fs from "fs-extra";
|
||||
import * as path from "path";
|
||||
import * as dotenv from "dotenv";
|
||||
import * as fs from "fs-extra";
|
||||
import monacoEditorPlugin from "vite-plugin-monaco-editor";
|
||||
import visualizer from "rollup-plugin-visualizer";
|
||||
import { visualizer } from "rollup-plugin-visualizer";
|
||||
import "dotenv/config";
|
||||
|
||||
import istanbul from "vite-plugin-istanbul";
|
||||
@@ -43,7 +43,7 @@ const isTesting = process.env.NODE_ENV === "test";
|
||||
|
||||
const enterpriseResolverPlugin = {
|
||||
name: "enterprise-resolver",
|
||||
async resolveId(source) {
|
||||
async resolveId(source: string) {
|
||||
if (source.startsWith("@zo/")) {
|
||||
const fileName = source.replace("@zo/", "");
|
||||
|
||||
@@ -69,7 +69,7 @@ function monacoEditorTestResolver() {
|
||||
return {
|
||||
name: "monaco-editor-test-resolver",
|
||||
enforce: "post",
|
||||
resolveId(id) {
|
||||
resolveId(id: string) {
|
||||
if (id === "monaco-editor") {
|
||||
return {
|
||||
id: "monaco-editor/esm/vs/editor/editor.api",
|
||||
@@ -116,21 +116,21 @@ export default defineConfig({
|
||||
process.env.VITE_COVERAGE === "true" &&
|
||||
istanbul({
|
||||
include: "src/**/*",
|
||||
exclude: ["node_modules", "test/"],
|
||||
exclude: ["node_modules", "test/", "src/**/*.spec.{ts,js}"],
|
||||
extension: [".js", ".ts", ".vue"],
|
||||
requireEnv: false,
|
||||
forceBuildInstrument: true,
|
||||
}),
|
||||
enterpriseResolverPlugin,
|
||||
vueJsx(),
|
||||
monacoEditorPlugin.default({
|
||||
(monacoEditorPlugin as any).default({
|
||||
customDistPath: () => path.resolve(__dirname, "dist/monacoeditorwork"),
|
||||
}),
|
||||
isTesting && monacoEditorTestResolver(),
|
||||
].filter(Boolean),
|
||||
resolve: {
|
||||
alias: {
|
||||
"@": fileURLToPath(new URL("./src", import.meta.url)),
|
||||
"@": fileURLToPath(new URL('./src', import.meta.url)),
|
||||
"@enterprise": fileURLToPath(
|
||||
new URL("./src/enterprise", import.meta.url),
|
||||
),
|
||||
@@ -148,8 +148,8 @@ export default defineConfig({
|
||||
chunkSizeWarningLimit: 3000,
|
||||
rollupOptions: {
|
||||
plugins: [
|
||||
nodePolyfills(),
|
||||
visualizer.default({
|
||||
nodePolyfills() as any,
|
||||
visualizer({
|
||||
open: true,
|
||||
gzipSize: true,
|
||||
brotliSize: true,
|
||||
@@ -185,43 +185,5 @@ export default defineConfig({
|
||||
plugins: [NodeGlobalsPolyfillPlugin({ buffer: true })],
|
||||
target: "es2020",
|
||||
},
|
||||
},
|
||||
test: {
|
||||
enable: true,
|
||||
global: true,
|
||||
setupFiles: "test/unit/helpers/setupTests.ts",
|
||||
deps: {
|
||||
inline: ["monaco-editor", "vitest-canvas-mock"],
|
||||
},
|
||||
coverage: {
|
||||
reporter: ["text", "json", "html"],
|
||||
all: true,
|
||||
exclude: [
|
||||
"coverage/**",
|
||||
"dist/**",
|
||||
"packages/*/test{,s}/**",
|
||||
"cypress/**",
|
||||
"src/test/**",
|
||||
"test{,s}/**",
|
||||
"test{,-*}.{js,cjs,mjs,ts,tsx,jsx}",
|
||||
"**/*{.,-}test.{js,cjs,mjs,ts,tsx,jsx}",
|
||||
"**/*{.,-}spec.{js,cjs,mjs,ts,tsx,jsx}",
|
||||
"**/__tests__/**",
|
||||
"**/{karma,rollup,webpack,vite,vitest,jest,ava,babel,nyc,cypress,tsup,build}.config.*",
|
||||
"**/.{eslint,mocha,prettier}rc.{js,cjs,yml}",
|
||||
"quasar.conf.js",
|
||||
"env.d.ts",
|
||||
],
|
||||
},
|
||||
threads: false,
|
||||
environment: "jsdom",
|
||||
cache: false,
|
||||
maxConcurrency: 20,
|
||||
update: false,
|
||||
environmentOptions: {
|
||||
jsdom: {
|
||||
resources: "usable",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { mergeConfig, defineConfig, configDefaults } from 'vitest/config'
|
||||
import type { ConfigEnv } from 'vitest/config'
|
||||
import type { UserConfig } from 'vite'
|
||||
import viteConfig from './vite.config'
|
||||
|
||||
// Convert the vite config to a plain object if it's a function
|
||||
const viteConfigObj = typeof viteConfig === 'function'
|
||||
? (viteConfig as (options: ConfigEnv) => UserConfig)({ command: 'serve', mode: 'development' })
|
||||
: viteConfig
|
||||
|
||||
export default mergeConfig(
|
||||
viteConfigObj,
|
||||
defineConfig({
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||
}
|
||||
},
|
||||
test: {
|
||||
environment: 'jsdom',
|
||||
exclude: [...configDefaults.exclude, 'e2e/**'],
|
||||
include: ["src/**/*.spec.{ts,js,vue}"],
|
||||
root: fileURLToPath(new URL('.', import.meta.url)),
|
||||
setupFiles: ['src/test/unit/helpers/setupTests.ts'],
|
||||
deps: {
|
||||
inline: ["monaco-editor", "vitest-canvas-mock"],
|
||||
},
|
||||
coverage: {
|
||||
reporter: ["text", "json", "html"],
|
||||
all: true,
|
||||
exclude: [
|
||||
"coverage/**",
|
||||
"dist/**",
|
||||
"packages/*/test{,s}/**",
|
||||
"cypress/**",
|
||||
"src/test/**",
|
||||
"test{,s}/**",
|
||||
"test{,-*}.{js,cjs,mjs,ts,tsx,jsx}",
|
||||
"**/*{.,-}test.{js,cjs,mjs,ts,tsx,jsx}",
|
||||
"**/*{.,-}spec.{js,cjs,mjs,ts,tsx,jsx}",
|
||||
"**/__tests__/**",
|
||||
"**/{karma,rollup,webpack,vite,vitest,jest,ava,babel,nyc,cypress,tsup,build}.config.*",
|
||||
"**/.{eslint,mocha,prettier}rc.{js,cjs,yml}",
|
||||
"quasar.conf.js",
|
||||
"env.d.ts",
|
||||
],
|
||||
},
|
||||
},
|
||||
}),
|
||||
)
|
||||
|
||||
|
||||
// import { defineConfig } from 'vitest/config';
|
||||
// import path from 'path';
|
||||
// import vue from '@vitejs/plugin-vue'
|
||||
// import { quasar } from "@quasar/vite-plugin";
|
||||
|
||||
// export default defineConfig({
|
||||
// plugins: [vue(), quasar()],
|
||||
// test: {
|
||||
// globals: true,
|
||||
// setupFiles: "test/unit/helpers/setupTests.ts",
|
||||
// deps: {
|
||||
// inline: ["monaco-editor", "vitest-canvas-mock"],
|
||||
// },
|
||||
// coverage: {
|
||||
// reporter: ["text", "json", "html"],
|
||||
// all: true,
|
||||
// exclude: [
|
||||
// "coverage/**",
|
||||
// "dist/**",
|
||||
// "packages/*/test{,s}/**",
|
||||
// "cypress/**",
|
||||
// "src/test/**",
|
||||
// "test{,s}/**",
|
||||
// "test{,-*}.{js,cjs,mjs,ts,tsx,jsx}",
|
||||
// "**/*{.,-}test.{js,cjs,mjs,ts,tsx,jsx}",
|
||||
// "**/*{.,-}spec.{js,cjs,mjs,ts,tsx,jsx}",
|
||||
// "**/__tests__/**",
|
||||
// "**/{karma,rollup,webpack,vite,vitest,jest,ava,babel,nyc,cypress,tsup,build}.config.*",
|
||||
// "**/.{eslint,mocha,prettier}rc.{js,cjs,yml}",
|
||||
// "quasar.conf.js",
|
||||
// "env.d.ts",
|
||||
// ],
|
||||
// },
|
||||
// environment: "jsdom",
|
||||
// environmentOptions: {
|
||||
// jsdom: {
|
||||
// resources: "usable",
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// resolve: {
|
||||
// alias: {
|
||||
// '@': path.resolve(__dirname, './src'),
|
||||
// },
|
||||
// },
|
||||
// });
|
||||
Reference in New Issue
Block a user