diff --git a/assets/javascripts/discourse/components/query-result.js b/assets/javascripts/discourse/components/query-result.js index 4d1a926..b2282e0 100644 --- a/assets/javascripts/discourse/components/query-result.js +++ b/assets/javascripts/discourse/components/query-result.js @@ -295,7 +295,7 @@ function randomIdShort() { function transformedRelTable(table, modelClass) { const result = {}; - table.forEach((item) => { + table?.forEach((item) => { if (modelClass) { result[item.id] = modelClass.create(item); } else { diff --git a/test/javascripts/acceptance/list-queries-test.js b/test/javascripts/acceptance/list-queries-test.js index 362d4d4..3d1615b 100644 --- a/test/javascripts/acceptance/list-queries-test.js +++ b/test/javascripts/acceptance/list-queries-test.js @@ -1,20 +1,11 @@ import { visit } from "@ember/test-helpers"; import { test } from "qunit"; -import { clearPopupMenuOptionsCallback } from "discourse/controllers/composer"; -import { - acceptance, - count, - exists, - query, -} from "discourse/tests/helpers/qunit-helpers"; -import I18n from "I18n"; +import { acceptance } from "discourse/tests/helpers/qunit-helpers"; +import I18n from "discourse-i18n"; acceptance("Data Explorer Plugin | List Queries", function (needs) { needs.user(); needs.settings({ data_explorer_enabled: true }); - needs.hooks.beforeEach(() => { - clearPopupMenuOptionsCallback(); - }); needs.pretender((server, helper) => { server.get("/admin/plugins/explorer/groups.json", () => { @@ -142,44 +133,38 @@ acceptance("Data Explorer Plugin | List Queries", function (needs) { }); }); - test("it renders the page with the list of queries", async function (assert) { + test("renders the page with the list of queries", async function (assert) { await visit("/admin/plugins/explorer"); - assert.ok( - query("div.query-list input.ember-text-field").placeholder === + assert + .dom("div.query-list input.ember-text-field") + .hasAttribute( + "placeholder", I18n.t("explorer.search_placeholder"), - "the search box was rendered" - ); + "the search box was rendered" + ); - assert.ok( - exists("div.query-list button.btn-icon svg.d-icon-plus"), - "the add query button was rendered" - ); + assert + .dom("div.query-list button.btn-icon svg.d-icon-plus") + .exists("the add query button was rendered"); - assert.ok( - query("div.query-list button.btn-icon-text span.d-button-label") - .innerText === I18n.t("explorer.import.label"), - "the import button was rendered" - ); + assert + .dom("div.query-list button.btn-icon-text span.d-button-label") + .hasText( + I18n.t("explorer.import.label"), + "the import button was rendered" + ); - assert.equal( - count("div.container table.recent-queries tbody tr"), - 2, - "the list of queries was rendered" - ); + assert + .dom("div.container table.recent-queries tbody tr") + .exists({ count: 2 }, "the list of queries was rendered"); - assert.ok( - query( - "div.container table.recent-queries tbody tr:nth-child(1) td a" - ).innerText.startsWith("Top 100 Likers"), - "The first query was rendered" - ); + assert + .dom("div.container table.recent-queries tbody tr:nth-child(1) td a") + .hasText(/^\s*Top 100 Likers/, "The first query was rendered"); - assert.ok( - query( - "div.container table.recent-queries tbody tr:nth-child(2) td a" - ).innerText.startsWith("Top 100 Active Topics"), - "The second query was rendered" - ); + assert + .dom("div.container table.recent-queries tbody tr:nth-child(2) td a") + .hasText(/^\s*Top 100 Active Topics/, "The second query was rendered"); }); }); diff --git a/test/javascripts/acceptance/new-query-test.js b/test/javascripts/acceptance/new-query-test.js index 7376e95..b25ab23 100644 --- a/test/javascripts/acceptance/new-query-test.js +++ b/test/javascripts/acceptance/new-query-test.js @@ -1,14 +1,10 @@ import { click, currentURL, fillIn, visit } from "@ember/test-helpers"; import { test } from "qunit"; -import { clearPopupMenuOptionsCallback } from "discourse/controllers/composer"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; acceptance("Data Explorer Plugin | New Query", function (needs) { needs.user(); needs.settings({ data_explorer_enabled: true }); - needs.hooks.beforeEach(() => { - clearPopupMenuOptionsCallback(); - }); needs.pretender((server, helper) => { server.get("/admin/plugins/explorer/groups.json", () => { @@ -61,6 +57,6 @@ acceptance("Data Explorer Plugin | New Query", function (needs) { // select create new query button await click(".query-create button"); - assert.equal(currentURL(), "/admin/plugins/explorer?id=-15"); + assert.strictEqual(currentURL(), "/admin/plugins/explorer?id=-15"); }); }); diff --git a/test/javascripts/acceptance/param-input-test.js b/test/javascripts/acceptance/param-input-test.js index eef0611..6397e72 100644 --- a/test/javascripts/acceptance/param-input-test.js +++ b/test/javascripts/acceptance/param-input-test.js @@ -1,10 +1,6 @@ import { click, currentURL, fillIn, visit } from "@ember/test-helpers"; import { test } from "qunit"; -import { - acceptance, - exists, - query, -} from "discourse/tests/helpers/qunit-helpers"; +import { acceptance } from "discourse/tests/helpers/qunit-helpers"; acceptance("Data Explorer Plugin | Param Input", function (needs) { needs.user(); @@ -327,6 +323,7 @@ acceptance("Data Explorer Plugin | Param Input", function (needs) { }, }); }); + server.put("/admin/plugins/explorer/queries/3", () => { return helper.response({ query: { @@ -353,7 +350,7 @@ acceptance("Data Explorer Plugin | Param Input", function (needs) { }); }); - test("it puts params for the query into the url", async function (assert) { + test("puts params for the query into the url", async function (assert) { await visit("/admin/plugins/explorer?id=-6"); const monthsAgoValue = "2"; await fillIn(".query-params input", monthsAgoValue); @@ -361,10 +358,10 @@ acceptance("Data Explorer Plugin | Param Input", function (needs) { const searchParams = new URLSearchParams(currentURL().split("?")[1]); const monthsAgoParam = JSON.parse(searchParams.get("params")).months_ago; - assert.equal(monthsAgoParam, monthsAgoValue); + assert.strictEqual(monthsAgoParam, monthsAgoValue); }); - test("it puts params for the query into the url for group reports", async function (assert) { + test("puts params for the query into the url for group reports", async function (assert) { await visit("/g/discourse/reports/-8"); const monthsAgoValue = "2"; await fillIn(".query-params input", monthsAgoValue); @@ -372,32 +369,32 @@ acceptance("Data Explorer Plugin | Param Input", function (needs) { const searchParams = new URLSearchParams(currentURL().split("?")[1]); const monthsAgoParam = JSON.parse(searchParams.get("params")).months_ago; - assert.equal(monthsAgoParam, monthsAgoValue); + assert.strictEqual(monthsAgoParam, monthsAgoValue); }); - test("it loads the page if one of the parameter is null", async function (assert) { + test("loads the page if one of the parameter is null", async function (assert) { await visit('/admin/plugins/explorer?id=-7¶ms={"user":null}'); - assert.ok(exists(".query-params .user-chooser")); - assert.ok(exists(".query-run .btn.btn-primary")); + assert.dom(".query-params .user-chooser").exists(); + assert.dom(".query-run .btn.btn-primary").exists(); }); - test("it loads the page if one of the parameter is null for group reports", async function (assert) { + test("loads the page if one of the parameter is null for group reports", async function (assert) { await visit('/g/discourse/reports/-8?params={"months_ago":null}'); - assert.ok(exists(".query-params input")); - assert.ok(exists(".query-run .btn.btn-primary")); + assert.dom(".query-params input").exists(); + assert.dom(".query-run .btn.btn-primary").exists(); }); - test("it applies params when running a report", async function (assert) { + test("applies params when running a report", async function (assert) { await visit("/g/discourse/reports/-8"); const monthsAgoValue = "2"; await fillIn(".query-params input", monthsAgoValue); await click("form.query-run button"); - assert.equal(query(".query-params input").value, monthsAgoValue); + assert.dom(".query-params input").hasValue(monthsAgoValue); }); - test("it creates input boxes if has parameters when save", async function (assert) { + test("creates input boxes if has parameters when save", async function (assert) { await visit("/admin/plugins/explorer?id=3"); - assert.notOk(exists(".query-params input")); + assert.dom(".query-params input").doesNotExist(); await click(".query-edit .btn-edit-query"); await click(".query-editor .ace_text-input"); await fillIn( @@ -405,6 +402,6 @@ acceptance("Data Explorer Plugin | Param Input", function (needs) { "-- [params]\n-- int :months_ago = 1\n\nSELECT 1" ); await click(".query-edit .btn-save-query"); - assert.ok(exists(".query-params input")); + assert.dom(".query-params input").exists(); }); }); diff --git a/test/javascripts/acceptance/run-query-test.js b/test/javascripts/acceptance/run-query-test.js index 06d197a..97c0ffc 100644 --- a/test/javascripts/acceptance/run-query-test.js +++ b/test/javascripts/acceptance/run-query-test.js @@ -1,20 +1,11 @@ import { click, visit } from "@ember/test-helpers"; import { test } from "qunit"; -import { clearPopupMenuOptionsCallback } from "discourse/controllers/composer"; -import { - acceptance, - exists, - query, - queryAll, -} from "discourse/tests/helpers/qunit-helpers"; -import I18n from "I18n"; +import { acceptance } from "discourse/tests/helpers/qunit-helpers"; +import I18n from "discourse-i18n"; acceptance("Data Explorer Plugin | Run Query", function (needs) { needs.user(); needs.settings({ data_explorer_enabled: true }); - needs.hooks.beforeEach(() => { - clearPopupMenuOptionsCallback(); - }); needs.pretender((server, helper) => { server.get("/admin/plugins/explorer/groups.json", () => { @@ -185,71 +176,57 @@ acceptance("Data Explorer Plugin | Run Query", function (needs) { }); }); - test("it runs query and renders data and a chart", async function (assert) { + test("runs query and renders data and a chart", async function (assert) { await visit("/admin/plugins/explorer?id=-6"); - assert.ok( - query("div.name h1").innerText.trim() === "Top 100 Likers", - "the query name was rendered" - ); + assert + .dom("div.name h1") + .hasText("Top 100 Likers", "the query name was rendered"); - assert.ok(exists("div.query-edit"), "the query code was rendered"); + assert.dom("div.query-edit").exists("the query code was rendered"); - assert.ok( - query("form.query-run button span").innerText.trim() === - I18n.t("explorer.run"), - "the run button was rendered" - ); + assert + .dom("form.query-run button span") + .hasText(I18n.t("explorer.run"), "the run button was rendered"); await click("form.query-run button"); - assert.ok( - queryAll("div.query-results table tbody tr").length === 2, - "the table with query results was rendered" - ); + assert + .dom("div.query-results table tbody tr") + .exists({ count: 2 }, "the table with query results was rendered"); - assert.ok( - query("div.result-info button:nth-child(3) span").innerText.trim() === - I18n.t("explorer.show_graph"), - "the chart button was rendered" - ); + assert + .dom("div.result-info button:nth-child(3) span") + .hasText(I18n.t("explorer.show_graph"), "the chart button was rendered"); await click("div.result-info button:nth-child(3)"); - assert.ok(exists("canvas"), "the chart was rendered"); + assert.dom("canvas").exists("the chart was rendered"); }); - test("it runs query and renders 0, false, and NULL values correctly", async function (assert) { + test("runs query and renders 0, false, and NULL values correctly", async function (assert) { await visit("/admin/plugins/explorer?id=2"); - assert.ok( - query("div.name h1").innerText.trim() === "What about 0?", - "the query name was rendered" - ); + assert + .dom("div.name h1") + .hasText("What about 0?", "the query name was rendered"); - assert.ok( - query("form.query-run button span").innerText.trim() === - I18n.t("explorer.run"), - "the run button was rendered" - ); + assert + .dom("form.query-run button span") + .hasText(I18n.t("explorer.run"), "the run button was rendered"); await click("form.query-run button"); - assert.ok( - query("div.query-results tbody td:nth-child(1)").innerText.trim() === "0", - "renders '0' values" - ); + assert + .dom("div.query-results tbody td:nth-child(1)") + .hasText("0", "renders '0' values"); - assert.ok( - query("div.query-results tbody td:nth-child(2)").innerText.trim() === - "NULL", - "renders 'NULL' values" - ); + assert + .dom("div.query-results tbody td:nth-child(2)") + .hasText("NULL", "renders 'NULL' values"); - assert.ok( - query("div.query-results tbody td:nth-child(3)").innerText.trim() === - "false", - "renders 'false' values" - ); + assert + .dom("div.query-results tbody td:nth-child(3)") + .hasText("false", "renders 'false' values"); }); }); diff --git a/test/javascripts/components/param-input-test.js b/test/javascripts/components/param-input-test.js index 0d718cc..287f8ff 100644 --- a/test/javascripts/components/param-input-test.js +++ b/test/javascripts/components/param-input-test.js @@ -276,7 +276,7 @@ module("Data Explorer Plugin | Component | param-input", function (hooks) { assert.rejects(this.submit()); }); - test("async normalizion", async function (assert) { + test("async normalization", async function (assert) { this.setProperties({ param_info: [ { diff --git a/test/javascripts/integration/components/data-explorer-bar-chart-test.gjs b/test/javascripts/integration/components/data-explorer-bar-chart-test.gjs new file mode 100644 index 0000000..24a02d5 --- /dev/null +++ b/test/javascripts/integration/components/data-explorer-bar-chart-test.gjs @@ -0,0 +1,24 @@ +import { array } from "@ember/helper"; +import { render } from "@ember/test-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import DataExplorerBarChart from "../../discourse/components/data-explorer-bar-chart"; + +module( + "Data Explorer Plugin | Integration | Component | data-explorer-bar-chart", + function (hooks) { + setupRenderingTest(hooks); + + test("renders a chart", async function (assert) { + await render(); + + assert.dom("canvas").exists("renders a canvas"); + }); + } +); diff --git a/test/javascripts/integration/components/data-explorer-bar-chart-test.js b/test/javascripts/integration/components/data-explorer-bar-chart-test.js deleted file mode 100644 index 992b0a5..0000000 --- a/test/javascripts/integration/components/data-explorer-bar-chart-test.js +++ /dev/null @@ -1,26 +0,0 @@ -import hbs from "htmlbars-inline-precompile"; -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { discourseModule, exists } from "discourse/tests/helpers/qunit-helpers"; - -discourseModule( - "Data Explorer Plugin | Integration | Component | data-explorer-bar-chart", - function (hooks) { - setupRenderingTest(hooks); - - componentTest("it renders a chart", { - template: hbs`{{data-explorer-bar-chart}}`, - - beforeEach() { - this.set("labels", ["label_1", "label_2"]); - this.set("values", [115, 1000]); - this.set("datasetName", "data"); - }, - - async test(assert) { - assert.ok(exists("canvas"), "it renders a canvas"); - }, - }); - } -); diff --git a/test/javascripts/integration/components/query-result-test.gjs b/test/javascripts/integration/components/query-result-test.gjs new file mode 100644 index 0000000..9f7d354 --- /dev/null +++ b/test/javascripts/integration/components/query-result-test.gjs @@ -0,0 +1,268 @@ +import { click, render } from "@ember/test-helpers"; +import { module, test } from "qunit"; +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import I18n from "discourse-i18n"; +import QueryResult from "../../discourse/components/query-result"; + +module( + "Data Explorer Plugin | Integration | Component | query-result", + function (hooks) { + setupRenderingTest(hooks); + + test("renders query results", async function (assert) { + const content = { + colrender: [], + result_count: 2, + columns: ["user_name", "like_count"], + rows: [ + ["user1", 10], + ["user2", 20], + ], + }; + + await render(); + + assert + .dom("div.result-info button:nth-child(1) span") + .hasText(I18n.t("explorer.download_json"), "renders the JSON button"); + + assert + .dom("div.result-info button:nth-child(2) span") + .hasText(I18n.t("explorer.download_csv"), "renders the CSV button"); + + assert + .dom("div.result-info button:nth-child(3) span") + .hasText(I18n.t("explorer.show_graph"), "renders the chart button"); + + assert.dom("div.result-about").exists("renders a query summary"); + + assert.dom("table thead tr th:nth-child(1)").hasText("user_name"); + assert.dom("table thead tr th:nth-child(2)").hasText("like_count"); + assert + .dom("table tbody tr:nth-child(1) td:nth-child(1)") + .hasText("user1"); + assert.dom("table tbody tr:nth-child(1) td:nth-child(2)").hasText("10"); + assert + .dom("table tbody tr:nth-child(2) td:nth-child(1)") + .hasText("user2"); + assert.dom("table tbody tr:nth-child(2) td:nth-child(2)").hasText("20"); + }); + + test("renders badge names in query results", async function (assert) { + const content = { + colrender: { 0: "badge" }, + relations: { + badge: [ + { + description: "description", + icon: "fa-user", + id: 1, + name: "badge name", + display_name: "badge display name", + }, + ], + }, + result_count: 1, + columns: ["badge_id"], + rows: [[1]], + }; + + await render(); + + assert + .dom("table tbody tr:nth-child(1) td:nth-child(1) span") + .hasText("badge display name"); + }); + + test("renders a post in query results", async function (assert) { + const content = { + colrender: { 0: "post" }, + relations: { + post: [ + { + description: "description", + id: 1, + topic_id: 1, + post_number: 1, + excerpt: "foo", + username: "user1", + avatar_template: "", + }, + ], + }, + result_count: 1, + columns: [""], + rows: [[1]], + }; + + await render(); + + assert + .dom("table tbody tr:nth-child(1) td:nth-child(1) aside") + .hasAttribute("data-post", "1"); + assert + .dom("table tbody tr:nth-child(1) td:nth-child(1) aside") + .hasAttribute("data-topic", "1"); + }); + + test("renders a category_id in query results", async function (assert) { + const content = { + colrender: { 0: "category" }, + relations: { + category: [ + { + id: 1, + name: "foo", + slug: "foo", + topic_count: 0, + position: 1, + description: "a category", + can_edit: true, + }, + ], + }, + result_count: 1, + columns: [""], + rows: [[1]], + }; + + await render(); + + assert + .dom( + "table tbody tr:nth-child(1) td:nth-child(1) .badge-category__name" + ) + .exists(); + }); + } +); + +module( + "Data Explorer Plugin | Integration | Component | query-result | chart", + function (hooks) { + setupRenderingTest(hooks); + + test("navigation between a table and a chart works", async function (assert) { + const content = { + colrender: [], + result_count: 2, + columns: ["user_name", "like_count"], + rows: [ + ["user1", 10], + ["user2", 20], + ], + }; + + await render(); + + assert + .dom("div.result-info button:nth-child(3) span") + .hasText( + I18n.t("explorer.show_graph"), + "the chart button was rendered" + ); + assert.dom("table").exists("the table was rendered"); + + await click("div.result-info button:nth-child(3)"); + + assert + .dom("div.result-info button:nth-child(3) span") + .hasText( + I18n.t("explorer.show_table"), + "the chart button was changed to the table button" + ); + assert.dom("canvas").exists("the chart was rendered"); + + await click("div.result-info button:nth-child(3)"); + assert + .dom("div.result-info button:nth-child(3) span") + .hasText( + I18n.t("explorer.show_graph"), + "the table button was changed to the chart button" + ); + assert.dom("table").exists("the table was rendered"); + }); + + test("renders a chart button when data has two columns and numbers in the second column", async function (assert) { + const content = { + colrender: [], + result_count: 2, + columns: ["user_name", "like_count"], + rows: [ + ["user1", 10], + ["user2", 20], + ], + }; + + await render(); + + assert + .dom("div.result-info button:nth-child(3) span") + .hasText(I18n.t("explorer.show_graph")); + }); + + test("doesn't render a chart button when data contains identifiers in the second column", async function (assert) { + const content = { + colrender: { 1: "user" }, + relations: { + user: [ + { id: 1, username: "user1" }, + { id: 2, username: "user2" }, + ], + }, + result_count: 2, + columns: ["topic_id", "user_id"], + rows: [ + [1, 10], + [2, 20], + ], + }; + + await render(); + + assert.dom("div.result-info button:nth-child(3)").doesNotExist(); + }); + + test("doesn't render a chart button when data contains one column", async function (assert) { + const content = { + colrender: [], + result_count: 2, + columns: ["user_name"], + rows: [["user1"], ["user2"]], + }; + + await render(); + + assert.dom("div.result-info button:nth-child(3)").doesNotExist(); + }); + + test("doesn't render a chart button when data contains more than two columns", async function (assert) { + const content = { + colrender: [], + result_count: 2, + columns: ["user_name", "like_count", "post_count"], + rows: [ + ["user1", 10, 1], + ["user2", 20, 2], + ], + }; + + await render(); + + assert.dom("div.result-info button:nth-child(3)").doesNotExist(); + }); + + test("handles no results", async function (assert) { + const content = { + colrender: [], + result_count: 0, + columns: ["user_name", "like_count", "post_count"], + rows: [], + }; + + await render(); + + assert.dom("table tbody tr").doesNotExist("renders no results"); + }); + } +); diff --git a/test/javascripts/integration/components/query-result-test.js b/test/javascripts/integration/components/query-result-test.js deleted file mode 100644 index dc574e9..0000000 --- a/test/javascripts/integration/components/query-result-test.js +++ /dev/null @@ -1,348 +0,0 @@ -import { click } from "@ember/test-helpers"; -import hbs from "htmlbars-inline-precompile"; -import componentTest, { - setupRenderingTest, -} from "discourse/tests/helpers/component-test"; -import { - discourseModule, - exists, - query, -} from "discourse/tests/helpers/qunit-helpers"; -import I18n from "I18n"; - -discourseModule( - "Data Explorer Plugin | Integration | Component | query-result", - function (hooks) { - setupRenderingTest(hooks); - - componentTest("it renders query results", { - template: hbs``, - - beforeEach() { - const results = { - colrender: [], - result_count: 2, - columns: ["user_name", "like_count"], - rows: [ - ["user1", 10], - ["user2", 20], - ], - }; - this.set("content", results); - }, - - test(assert) { - assert.ok( - query("div.result-info button:nth-child(1) span").innerText === - I18n.t("explorer.download_json"), - "it renders the JSON button" - ); - - assert.ok( - query("div.result-info button:nth-child(2) span").innerText === - I18n.t("explorer.download_csv"), - "it renders the CSV button" - ); - - assert.ok( - query("div.result-info button:nth-child(3) span").innerText === - I18n.t("explorer.show_graph"), - "it renders the chart button" - ); - - assert.ok(exists("div.result-about"), "it renders a query summary"); - - assert.ok( - query("table thead tr th:nth-child(1)").innerText === "user_name" && - query("table thead tr th:nth-child(2)").innerText === - "like_count" && - query("table tbody tr:nth-child(1) td:nth-child(1)").innerText === - "user1" && - query("table tbody tr:nth-child(1) td:nth-child(2)").innerText === - "10" && - query("table tbody tr:nth-child(2) td:nth-child(1)").innerText === - "user2" && - query("table tbody tr:nth-child(2) td:nth-child(2)").innerText === - "20", - "it renders a table with data" - ); - }, - }); - - componentTest("it renders badge names in query results", { - template: hbs``, - - beforeEach() { - const results = { - colrender: { 0: "badge" }, - relations: { - badge: [ - { - description: "description", - icon: "fa-user", - id: 1, - name: "badge name", - display_name: "badge display name", - }, - ], - }, - result_count: 1, - columns: ["badge_id"], - rows: [[1]], - }; - this.set("content", results); - }, - - test(assert) { - assert.ok( - query("table tbody tr:nth-child(1) td:nth-child(1) span") - .innerText === "badge display name" - ); - }, - }); - - componentTest("it renders a post in query results", { - template: hbs``, - - beforeEach() { - const results = { - colrender: { 0: "post" }, - relations: { - post: [ - { - description: "description", - id: 1, - topic_id: 1, - post_number: 1, - excerpt: "foo", - username: "user1", - avatar_template: "", - }, - ], - }, - result_count: 1, - columns: [""], - rows: [[1]], - }; - this.set("content", results); - }, - - test(assert) { - assert.ok( - query("table tbody tr:nth-child(1) td:nth-child(1) aside").dataset - .post === "1" - ); - - assert.ok( - query("table tbody tr:nth-child(1) td:nth-child(1) aside").dataset - .topic === "1" - ); - }, - }); - - componentTest("it renders a category_id in query results", { - template: hbs``, - - beforeEach() { - const results = { - colrender: { 0: "category" }, - relations: { - category: [ - { - id: 1, - name: "foo", - slug: "foo", - topic_count: 0, - position: 1, - description: "a category", - can_edit: true, - }, - ], - }, - result_count: 1, - columns: [""], - rows: [[1]], - }; - this.set("content", results); - }, - - test(assert) { - assert.ok( - exists( - "table tbody tr:nth-child(1) td:nth-child(1) .badge-category__name" - ) - ); - }, - }); - } -); - -discourseModule( - "Data Explorer Plugin | Integration | Component | query-result | chart", - function (hooks) { - setupRenderingTest(hooks); - - componentTest("navigation between a table and a chart works", { - template: hbs``, - - beforeEach() { - const results = { - colrender: [], - result_count: 2, - columns: ["user_name", "like_count"], - rows: [ - ["user1", 10], - ["user2", 20], - ], - }; - this.set("content", results); - }, - - async test(assert) { - assert.equal( - query("div.result-info button:nth-child(3) span").innerText, - I18n.t("explorer.show_graph"), - "the chart button was rendered" - ); - assert.ok(exists("table"), "the table was rendered"); - - await click("div.result-info button:nth-child(3)"); - - assert.equal( - query("div.result-info button:nth-child(3) span").innerText, - I18n.t("explorer.show_table"), - "the chart button was changed to the table button" - ); - assert.ok(exists("canvas"), "the chart was rendered"); - - await click("div.result-info button:nth-child(3)"); - assert.equal( - query("div.result-info button:nth-child(3) span").innerText, - I18n.t("explorer.show_graph"), - "the table button was changed to the chart button" - ); - assert.ok(exists("table"), "the table was rendered"); - }, - }); - - componentTest( - "it renders a chart button when data has two columns and numbers in the second column", - { - template: hbs``, - - beforeEach() { - const results = { - colrender: [], - result_count: 2, - columns: ["user_name", "like_count"], - rows: [ - ["user1", 10], - ["user2", 20], - ], - }; - this.set("content", results); - }, - - test(assert) { - assert.equal( - query("div.result-info button:nth-child(3) span").innerText, - I18n.t("explorer.show_graph") - ); - }, - } - ); - - componentTest( - "it doesn't render a chart button when data contains identifiers in the second column", - { - template: hbs``, - - beforeEach() { - const results = { - colrender: { 1: "user" }, - relations: { - user: [ - { id: 1, username: "user1" }, - { id: 2, username: "user2" }, - ], - }, - result_count: 2, - columns: ["topic_id", "user_id"], - rows: [ - [1, 10], - [2, 20], - ], - }; - this.set("content", results); - }, - - test(assert) { - assert.ok(!exists("div.result-info button:nth-child(3)")); - }, - } - ); - - componentTest( - "it doesn't render a chart button when data contains one column", - { - template: hbs``, - - beforeEach() { - const results = { - colrender: [], - result_count: 2, - columns: ["user_name"], - rows: [["user1"], ["user2"]], - }; - this.set("content", results); - }, - - test(assert) { - assert.ok(!exists("div.result-info button:nth-child(3)")); - }, - } - ); - - componentTest( - "it doesn't render a chart button when data contains more than two columns", - { - template: hbs``, - - beforeEach() { - const results = { - colrender: [], - result_count: 2, - columns: ["user_name", "like_count", "post_count"], - rows: [ - ["user1", 10, 1], - ["user2", 20, 2], - ], - }; - this.set("content", results); - }, - - test(assert) { - assert.ok(!exists("div.result-info button:nth-child(3)")); - }, - } - ); - - componentTest("it handles no results", { - template: hbs``, - - beforeEach() { - const results = { - colrender: [], - result_count: 0, - columns: ["user_name", "like_count", "post_count"], - rows: [], - }; - this.set("content", results); - }, - - test(assert) { - assert.ok(!exists("table tbody tr"), "renders no results"); - }, - }); - } -);