Skip to content

Commit

Permalink
test: replace usages of testdouble for containerHelpers object
Browse files Browse the repository at this point in the history
  • Loading branch information
edvald committed May 3, 2023
1 parent fd256b1 commit 50d7c92
Show file tree
Hide file tree
Showing 7 changed files with 219 additions and 144 deletions.
4 changes: 3 additions & 1 deletion core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@
"@types/react": "^18.0.28",
"@types/request": "^2.48.8",
"@types/request-promise": "^4.1.48",
"@types/sinon": "^10.0.14",
"@types/slice-ansi": "^5.0.0",
"@types/split2": "^3.2.1",
"@types/supertest": "^2.0.12",
Expand Down Expand Up @@ -231,7 +232,8 @@
"replace-in-file": "^6.3.5",
"serve-static": "^1.15.0",
"shx": "^0.3.4",
"testdouble": "^3.15.0",
"sinon": "^15.0.4",
"testdouble": "^3.17.2",
"testdouble-chai": "^0.5.0",
"timekeeper": "^2.2.0",
"touch": "^3.1.0",
Expand Down
12 changes: 0 additions & 12 deletions core/test/integ/setup.ts

This file was deleted.

155 changes: 61 additions & 94 deletions core/test/integ/src/plugins/container/container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

import sinon from "sinon"
import td from "testdouble"

import { PluginContext } from "../../../../../src/plugin-context"
import { gardenPlugin, ContainerProvider } from "../../../../../src/plugins/container/container"
import { expectError, getDataDir, getPropertyName, makeTestGarden, TestGarden } from "../../../../helpers"
import { expectError, getDataDir, makeTestGarden, TestGarden } from "../../../../helpers"
import { ActionLog, createActionLog } from "../../../../../src/logger/log-entry"
import { expect } from "chai"
import { ContainerBuildAction, ContainerBuildActionSpec } from "../../../../../src/plugins/container/moduleConfig"
Expand All @@ -21,6 +22,8 @@ import { BuildActionConfig } from "../../../../../src/actions/build"
import { containerHelpers, minDockerVersion } from "../../../../../src/plugins/container/helpers"
import { getDockerBuildFlags } from "../../../../../src/plugins/container/build"

const testVersionedId = "some/image:12345"

describe("plugins.container", () => {
const projectRoot = getDataDir("test-project-container")

Expand Down Expand Up @@ -51,16 +54,14 @@ describe("plugins.container", () => {
})

async function getTestBuild(cfg: BuildActionConfig): Promise<Executed<ContainerBuildAction>> {
td.replace(
containerHelpers,
getPropertyName(containerHelpers, (h) => h.actionHasDockerfile),
() => true
)
td.replace(
containerHelpers,
getPropertyName(containerHelpers, (h) => h.dockerCli),
() => ({ all: "test log", stdout: "some/image:12345" })
)
sinon.replace(containerHelpers, "actionHasDockerfile", async () => true)
sinon.replace(containerHelpers, "dockerCli", async () => ({
all: "test log",
stdout: testVersionedId,
stderr: "",
code: 0,
proc: <any>null,
}))

garden.setActionConfigs([cfg])
const graph = await garden.getConfigGraph({ emit: false, log })
Expand All @@ -72,116 +73,92 @@ describe("plugins.container", () => {
describe("publishContainerBuild", () => {
it("should publish image", async () => {
const config = cloneDeep(baseConfig)
config.spec.localId = "some/image:12345"
const action = td.object(await getTestBuild(config))
config.spec.localId = testVersionedId

td.replace(
containerHelpers,
getPropertyName(containerHelpers, (h) => h.actionHasDockerfile),
() => true
)
td.replace(
containerHelpers,
getPropertyName(containerHelpers, (h) => h.getPublicImageId),
() => "some/image:12345"
)
sinon.replace(containerHelpers, "getPublicImageId", () => testVersionedId)

const action = await getTestBuild(config)

sinon.restore()

sinon.replace(containerHelpers, "getPublicImageId", () => testVersionedId)
sinon.replace(containerHelpers, "actionHasDockerfile", async () => true)

td.replace(
containerHelpers,
getPropertyName(containerHelpers, (h) => h.dockerCli),
async ({ cwd, args, ctx: _ctx }) => {
if (args[0] === "tag") {
return { all: "log" }
}
expect(cwd).to.equal(action.getBuildPath())
expect(args).to.eql(["push", "some/image:12345"])
expect(_ctx).to.exist
return { all: "log" }
sinon.replace(containerHelpers, "dockerCli", async ({ cwd, args, ctx: _ctx }) => {
const out = { all: "log", stdout: "", stderr: "", code: 0, proc: <any>null }
if (args[0] === "tag") {
return out
}
)
expect(cwd).to.equal(action.getBuildPath())
expect(args).to.eql(["push", testVersionedId])
expect(_ctx).to.exist
return out
})

const result = await publishContainerBuild({ ctx, log, action })
expect(result.detail).to.eql({ message: "Published some/image:12345", published: true })
})

it("should tag image if remote id differs from local id", async () => {
const publishId = "some/image:1.1"

const config = cloneDeep(baseConfig)
config.spec.localId = "some/image:12345"
const action = td.object(await getTestBuild(config))

td.replace(action, "getOutput", (o: string) =>
o === "localImageId" ? "some/image:12345" : action.getOutput(<any>o)
)
td.replace(
containerHelpers,
getPropertyName(containerHelpers, (h) => h.getPublicImageId),
() => "some/image:1.1"
)
config.spec.publishId = publishId

const action = await getTestBuild(config)

const dockerCli = td.replace(
containerHelpers,
getPropertyName(containerHelpers, (h) => h.dockerCli)
sinon.replace(action, "getOutput", (o: string) =>
o === "localImageId" ? testVersionedId : action.getOutput(<any>o)
)
sinon.restore()

const dockerCli = sinon.stub(containerHelpers, "dockerCli")

const result = await publishContainerBuild({ ctx, log, action })
expect(result.detail).to.eql({ message: "Published some/image:1.1", published: true })

td.verify(
dockerCli({
cwd: action.getBuildPath(),
args: ["tag", "some/image:12345", "some/image:1.1"],
log: td.matchers.anything(),
ctx: td.matchers.anything(),
})
)
sinon.assert.calledWithMatch(dockerCli.firstCall, {
cwd: action.getBuildPath(),
args: ["tag", action.getOutput("local-image-id"), publishId],
})

td.verify(
dockerCli({
cwd: action.getBuildPath(),
args: ["push", "some/image:1.1"],
log: td.matchers.anything(),
ctx: td.matchers.anything(),
})
)
sinon.assert.calledWithMatch(dockerCli.secondCall, {
cwd: action.getBuildPath(),
args: ["push", publishId],
})
})

it("should use specified tag if provided", async () => {
const config = cloneDeep(baseConfig)
const action = td.object(await getTestBuild(config))

td.replace(
containerHelpers,
getPropertyName(containerHelpers, (h) => h.actionHasDockerfile),
() => true
)
sinon.restore()

td.replace(action, "getOutput", (o: string) =>
o === "localImageId" ? "some/image:12345" : action.getOutput(<any>o)
sinon.replace(action, "getOutput", (o: string) =>
o === "localImageId" ? testVersionedId : action.getOutput(<any>o)
)

const dockerCli = td.replace(
containerHelpers,
getPropertyName(containerHelpers, (h) => h.dockerCli)
)
sinon.replace(containerHelpers, "actionHasDockerfile", async () => true)

const dockerCli = sinon.stub(containerHelpers, "dockerCli")

const result = await publishContainerBuild({ ctx, log, action, tag: "custom-tag" })
expect(result.detail).to.eql({ message: "Published test:custom-tag", published: true })

td.verify(
dockerCli({
sinon.assert.calledWith(
dockerCli,
sinon.match({
cwd: action.getBuildPath(),
args: ["tag", "some/image:12345", "test:custom-tag"],
log: td.matchers.anything(),
ctx: td.matchers.anything(),
args: ["tag", testVersionedId, "test:custom-tag"],
})
)

td.verify(
dockerCli({
sinon.assert.calledWith(
dockerCli,
sinon.match({
cwd: action.getBuildPath(),
args: ["push", "test:custom-tag"],
log: td.matchers.anything(),
ctx: td.matchers.anything(),
})
)
})
Expand Down Expand Up @@ -232,11 +209,6 @@ describe("plugins.container", () => {

describe("getDockerBuildFlags", () => {
it("should include extraFlags", async () => {
td.replace(
containerHelpers,
getPropertyName(containerHelpers, (h) => h.actionHasDockerfile),
() => true
)
const config = cloneDeep(baseConfig)
config.spec.extraFlags = ["--cache-from", "some-image:latest"]

Expand All @@ -249,11 +221,6 @@ describe("plugins.container", () => {
})

it("should set GARDEN_ACTION_VERSION", async () => {
td.replace(
containerHelpers,
getPropertyName(containerHelpers, (h) => h.actionHasDockerfile),
() => true
)
const config = cloneDeep(baseConfig)

const buildAction = await getTestBuild(config)
Expand Down
2 changes: 2 additions & 0 deletions core/test/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

import sinon from "sinon"
import td from "testdouble"
import timekeeper from "timekeeper"
import { getDefaultProfiler } from "../src/util/profiling"
Expand Down Expand Up @@ -35,6 +36,7 @@ exports.mochaHooks = {
beforeEach() {},

afterEach() {
sinon.restore()
td.reset()
timekeeper.reset()
},
Expand Down
32 changes: 12 additions & 20 deletions core/test/unit/src/plugins/container/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/

import { expect } from "chai"
import td from "testdouble"
import sinon from "sinon"
import { ResolvedBuildAction, BuildActionConfig } from "../../../../../src/actions/build"
import { ConfigGraph } from "../../../../../src/graph/config-graph"
import { ActionLog, createActionLog, Log } from "../../../../../src/logger/log-entry"
Expand All @@ -16,7 +16,7 @@ import { buildContainer, getContainerBuildStatus } from "../../../../../src/plug
import { ContainerProvider, gardenPlugin } from "../../../../../src/plugins/container/container"
import { containerHelpers } from "../../../../../src/plugins/container/helpers"
import { joinWithPosix } from "../../../../../src/util/fs"
import { getDataDir, TestGarden, makeTestGarden, getPropertyName } from "../../../../helpers"
import { getDataDir, TestGarden, makeTestGarden } from "../../../../helpers"

context("build.ts", () => {
const projectRoot = getDataDir("test-project-container")
Expand All @@ -30,7 +30,7 @@ context("build.ts", () => {
beforeEach(async () => {
garden = await makeTestGarden(projectRoot, { plugins: [gardenPlugin()] })
log = garden.log
actionLog = createActionLog({ log: log, actionName: "", actionKind: "" })
actionLog = createActionLog({ log, actionName: "", actionKind: "" })
containerProvider = await garden.resolveProvider(garden.log, "container")
ctx = await garden.getPluginContext({ provider: containerProvider, templateContext: undefined, events: undefined })
graph = await garden.getConfigGraph({ log, emit: false })
Expand All @@ -41,23 +41,15 @@ context("build.ts", () => {
describe("getContainerBuildStatus", () => {
it("should return ready if build exists locally", async () => {
const action = await getAction()
td.replace(
containerHelpers,
getPropertyName(containerHelpers, (c) => c.imageExistsLocally),
async () => "fake image identifier string"
)
sinon.replace(containerHelpers, "imageExistsLocally", async () => "fake image identifier string")

const result = await getContainerBuildStatus({ ctx, log: actionLog, action })
expect(result.state).to.eql("ready")
})

it("should return not-ready if build does not exist locally", async () => {
const action = await getAction()
td.replace(
containerHelpers,
getPropertyName(containerHelpers, (c) => c.imageExistsLocally),
async () => null
)
sinon.replace(containerHelpers, "imageExistsLocally", async () => null)

const result = await getContainerBuildStatus({ ctx, log: actionLog, action })
expect(result.state).to.eql("not-ready")
Expand All @@ -66,7 +58,7 @@ context("build.ts", () => {

describe("buildContainer", () => {
beforeEach(() => {
td.replace(containerHelpers, "checkDockerServerVersion", () => null)
sinon.replace(containerHelpers, "checkDockerServerVersion", () => null)
})

function getCmdArgs(action: ResolvedBuildAction<BuildActionConfig<any, any>, any>, buildPath: string) {
Expand All @@ -87,16 +79,16 @@ context("build.ts", () => {
it("should build image if module contains Dockerfile", async () => {
const action = await getAction()

td.replace(action, "getOutputs", () => ({ localImageId: "some/image" }))
sinon.replace(action, "getOutputs", () => ({ localImageId: "some/image" }))

const buildPath = action.getBuildPath()

const cmdArgs = getCmdArgs(action, buildPath)
td.replace(containerHelpers, "dockerCli", async ({ cwd, args, ctx: _ctx }) => {
sinon.replace(containerHelpers, "dockerCli", async ({ cwd, args, ctx: _ctx }) => {
expect(cwd).to.equal(buildPath)
expect(args).to.eql(cmdArgs)
expect(_ctx).to.exist
return { all: "log" }
return { all: "log", stdout: "", stderr: "", code: 0, proc: <any>null }
})
const result = await buildContainer({ ctx, log: actionLog, action })
expect(result.state).to.eql("ready")
Expand All @@ -109,16 +101,16 @@ context("build.ts", () => {
const action = await getAction()
action.getSpec().dockerfile = "docker-dir/Dockerfile"

td.replace(action, "getOutputs", () => ({ localImageId: "some/image" }))
sinon.replace(action, "getOutputs", () => ({ localImageId: "some/image" }))

const buildPath = action.getBuildPath()

const cmdArgs = getCmdArgs(action, buildPath)
td.replace(containerHelpers, "dockerCli", async ({ cwd, args, ctx: _ctx }) => {
sinon.replace(containerHelpers, "dockerCli", async ({ cwd, args, ctx: _ctx }) => {
expect(cwd).to.equal(buildPath)
expect(args).to.eql(cmdArgs)
expect(_ctx).to.exist
return { all: "log" }
return { all: "log", stdout: "", stderr: "", code: 0, proc: <any>null }
})
const result = await buildContainer({ ctx, log: actionLog, action })
expect(result.state).to.eql("ready")
Expand Down
Loading

0 comments on commit 50d7c92

Please sign in to comment.