diff --git a/src/commands/query.mjs b/src/commands/query.mjs index 9538af28..2b2f8b4c 100644 --- a/src/commands/query.mjs +++ b/src/commands/query.mjs @@ -13,7 +13,6 @@ import { } from "../lib/errors.mjs"; import { formatError, - formatQueryInfo, formatQueryResponse, getSecret, } from "../lib/fauna-client.mjs"; @@ -71,6 +70,7 @@ const resolveInput = (argv) => { }; async function queryCommand(argv) { + const formatQueryInfo = container.resolve("formatQueryInfo"); const logger = container.resolve("logger"); // Run validation here instead of via check for more control over output diff --git a/src/commands/shell.mjs b/src/commands/shell.mjs index 2f338414..7a25fe2a 100644 --- a/src/commands/shell.mjs +++ b/src/commands/shell.mjs @@ -12,11 +12,7 @@ import { validateDatabaseOrSecret, yargsWithCommonConfigurableQueryOptions, } from "../lib/command-helpers.mjs"; -import { - formatQueryInfo, - formatQueryResponse, - getSecret, -} from "../lib/fauna-client.mjs"; +import { formatQueryResponse, getSecret } from "../lib/fauna-client.mjs"; import { clearHistoryStorage, initHistoryStorage } from "../lib/file-util.mjs"; async function shellCommand(argv) { @@ -150,8 +146,9 @@ const getArgvOrCtx = (key, argv, ctx) => { // caches the logger, client, and performQuery for subsequent shell calls async function buildCustomEval(argv) { - const runQueryFromString = container.resolve("runQueryFromString"); const formatError = container.resolve("formatError"); + const formatQueryInfo = container.resolve("formatQueryInfo"); + const runQueryFromString = container.resolve("runQueryFromString"); return async (cmd, ctx, _filename, cb) => { try { diff --git a/src/config/setup-container.mjs b/src/config/setup-container.mjs index e9d14a60..600ffffe 100644 --- a/src/config/setup-container.mjs +++ b/src/config/setup-container.mjs @@ -22,6 +22,7 @@ import { makeRetryableFaunaRequest } from "../lib/db.mjs"; import * as faunaV10 from "../lib/fauna.mjs"; import { formatError, + formatQueryInfo, isQueryable, runQueryFromString, } from "../lib/fauna-client.mjs"; @@ -98,6 +99,7 @@ export const injectables = { // utilities for interacting with Fauna runQueryFromString: awilix.asValue(runQueryFromString), formatError: awilix.asValue(formatError), + formatQueryInfo: awilix.asValue(formatQueryInfo), faunaClientV10: awilix.asValue(faunaV10), faunaClientV4: awilix.asValue(faunaV4), isQueryable: awilix.asValue(isQueryable), diff --git a/src/config/setup-test-container.mjs b/src/config/setup-test-container.mjs index 426863bf..aa33630b 100644 --- a/src/config/setup-test-container.mjs +++ b/src/config/setup-test-container.mjs @@ -11,6 +11,7 @@ import { f, InMemoryWritableStream } from "../../test/helpers.mjs"; import { parseYargs } from "../cli.mjs"; import { makeRetryableFaunaRequest } from "../lib/db.mjs"; import * as faunaClientV10 from "../lib/fauna.mjs"; +import { formatQueryInfo } from "../lib/fauna-client.mjs"; import * as faunaClientV4 from "../lib/faunadb.mjs"; import buildLogger from "../lib/logger.mjs"; import { injectables, setupCommonContainer } from "./setup-container.mjs"; @@ -106,6 +107,7 @@ export function setupTestContainer() { runQueryFromString: awilix.asValue(stub().resolves({})), isQueryable: awilix.asValue(stub().resolves()), formatError: awilix.asValue(stub()), + formatQueryInfo: awilix.asValue(spy(formatQueryInfo)), faunaClientV10: awilix.asValue({ getClient: stub(), runQuery: stub(), diff --git a/test/query.mjs b/test/query.mjs index 1c9ca24f..b3fbf3ba 100644 --- a/test/query.mjs +++ b/test/query.mjs @@ -6,6 +6,7 @@ import sinon from "sinon"; import { run } from "../src/cli.mjs"; import { setupTestContainer as setupContainer } from "../src/config/setup-test-container.mjs"; +import { QUERY_INFO_CHOICES } from "../src/lib/command-helpers.mjs"; import { NETWORK_ERROR_MESSAGE } from "../src/lib/errors.mjs"; import { colorize } from "../src/lib/formatting/colorize.mjs"; import { @@ -320,66 +321,91 @@ describe("query", function () { ); }); - // Add FormatQueryInfo to container in order to test which options are were passed - it.skip("can set the include option to an array"); - it.skip("can specify '--include all' to set all include options"); - it.skip("can specify '--include none' to set no include options"); + describe("query info", function () { + it("displays summary by default", async function () { + runQueryFromString.resolves({ + summary: "info at *query*:1: hello world", + data: "fql", + }); - it("displays summary by default", async function () { - runQueryFromString.resolves({ - summary: "info at *query*:1: hello world", - data: "fql", + await run( + `query "Database.all()" --performanceHints --secret=foo`, + container, + ); + + expect(logger.stderr).to.have.been.calledWith( + sinon.match(/hello world/), + ); + expect(container.resolve("codeToAnsi")).to.have.been.calledWith( + sinon.match(/hello world/), + "yaml", + ); + expect(logger.stdout).to.have.been.calledWith(sinon.match(/fql/)); }); - await run( - `query "Database.all()" --performanceHints --secret=foo`, - container, - ); + it("still displays performance hints if '--include none' is used", async function () { + runQueryFromString.resolves({ + summary: + "performance_hint: use a more efficient query\n1 | use a more efficient query", + data: "fql", + }); - expect(logger.stderr).to.have.been.calledWith(sinon.match(/hello world/)); - expect(container.resolve("codeToAnsi")).to.have.been.calledWith( - sinon.match(/hello world/), - "yaml", - ); - expect(logger.stdout).to.have.been.calledWith(sinon.match(/fql/)); - }); + await run( + `query "Database.all()" --performanceHints --secret=foo --include none`, + container, + ); - it("still displays performance hints if '--include none' is used", async function () { - runQueryFromString.resolves({ - summary: - "performance_hint: use a more efficient query\n1 | use a more efficient query", - data: "fql", + expect(logger.stderr).to.have.been.calledWith( + sinon.match(/use a more efficient query/), + ); + expect(container.resolve("codeToAnsi")).to.have.been.calledWith( + sinon.match(/use a more efficient query/), + "fql", + ); + expect(logger.stdout).to.have.been.calledWith(sinon.match(/fql/)); }); - await run( - `query "Database.all()" --performanceHints --secret=foo --include none`, - container, - ); + it("does not display anything if info fields are empty", async function () { + runQueryFromString.resolves({ + txn_ts: "", + schema_version: "", + summary: "", + query_tags: "", + stats: "", + data: "fql", + }); - expect(logger.stderr).to.have.been.calledWith( - sinon.match(/use a more efficient query/), - ); - expect(container.resolve("codeToAnsi")).to.have.been.calledWith( - sinon.match(/use a more efficient query/), - "fql", - ); - expect(logger.stdout).to.have.been.calledWith(sinon.match(/fql/)); - }); + await run(`query "test" --secret=foo --include all`, container); - it("does not display anything if info fields are empty", async function () { - runQueryFromString.resolves({ - txnTs: "", - schemaVersion: "", - summary: "", - queryTags: "", - stats: "", - data: "fql", + expect(logger.stderr).to.not.be.called; + expect(logger.stdout).to.have.been.calledWith(sinon.match(/fql/)); }); - await run(`query "Database.all()" --secret=foo --include all`, container); - - expect(logger.stderr).to.not.be.called; - expect(logger.stdout).to.have.been.calledWith(sinon.match(/fql/)); + QUERY_INFO_CHOICES.forEach((choice) => { + it(`displays ${choice} if '--include ${choice}' is used, but not others`, async function () { + runQueryFromString.resolves({ + txn_ts: "foo", + schema_version: "foo", + summary: "foo", + query_tags: "foo", + stats: "foo", + data: "fql", + }); + + await run(`query "test" --secret=foo --include ${choice}`, container); + + expect(logger.stderr).to.have.been.calledWith( + sinon.match(new RegExp(`${choice}:`)), + ); + + const ignoredChoices = QUERY_INFO_CHOICES.filter((o) => o !== choice); + for (const ignored of ignoredChoices) { + expect(logger.stderr).to.not.have.been.calledWith( + sinon.match(new RegExp(`${ignored}:`)), + ); + } + }); + }); }); it("can handle network errors", async function () {