General fixes for open handles, attempting to find and close all issues in server which are stopping shutdown of Jest suite.
This commit is contained in:
parent
4b7446fb37
commit
cf5316ec8d
|
@ -24,6 +24,7 @@ export * as redis from "./redis"
|
||||||
export * as locks from "./redis/redlockImpl"
|
export * as locks from "./redis/redlockImpl"
|
||||||
export * as utils from "./utils"
|
export * as utils from "./utils"
|
||||||
export * as errors from "./errors"
|
export * as errors from "./errors"
|
||||||
|
export * as timers from "./timers"
|
||||||
export { default as env } from "./environment"
|
export { default as env } from "./environment"
|
||||||
export { SearchParams } from "./db"
|
export { SearchParams } from "./db"
|
||||||
// Add context to tenancy for backwards compatibility
|
// Add context to tenancy for backwards compatibility
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { JobQueue } from "./constants"
|
||||||
import InMemoryQueue from "./inMemoryQueue"
|
import InMemoryQueue from "./inMemoryQueue"
|
||||||
import BullQueue from "bull"
|
import BullQueue from "bull"
|
||||||
import { addListeners, StalledFn } from "./listeners"
|
import { addListeners, StalledFn } from "./listeners"
|
||||||
|
import * as timers from "../timers"
|
||||||
|
|
||||||
const CLEANUP_PERIOD_MS = 60 * 1000
|
const CLEANUP_PERIOD_MS = 60 * 1000
|
||||||
let QUEUES: BullQueue.Queue[] | InMemoryQueue[] = []
|
let QUEUES: BullQueue.Queue[] | InMemoryQueue[] = []
|
||||||
|
@ -29,8 +30,8 @@ export function createQueue<T>(
|
||||||
}
|
}
|
||||||
addListeners(queue, jobQueue, opts?.removeStalledCb)
|
addListeners(queue, jobQueue, opts?.removeStalledCb)
|
||||||
QUEUES.push(queue)
|
QUEUES.push(queue)
|
||||||
if (!cleanupInterval) {
|
if (!cleanupInterval && !env.isTest()) {
|
||||||
cleanupInterval = setInterval(cleanup, CLEANUP_PERIOD_MS)
|
cleanupInterval = timers.set(cleanup, CLEANUP_PERIOD_MS)
|
||||||
// fire off an initial cleanup
|
// fire off an initial cleanup
|
||||||
cleanup().catch(err => {
|
cleanup().catch(err => {
|
||||||
console.error(`Unable to cleanup automation queue initially - ${err}`)
|
console.error(`Unable to cleanup automation queue initially - ${err}`)
|
||||||
|
@ -41,7 +42,7 @@ export function createQueue<T>(
|
||||||
|
|
||||||
export async function shutdown() {
|
export async function shutdown() {
|
||||||
if (cleanupInterval) {
|
if (cleanupInterval) {
|
||||||
clearInterval(cleanupInterval)
|
timers.clear(cleanupInterval)
|
||||||
}
|
}
|
||||||
if (QUEUES.length) {
|
if (QUEUES.length) {
|
||||||
for (let queue of QUEUES) {
|
for (let queue of QUEUES) {
|
||||||
|
|
|
@ -8,6 +8,7 @@ import {
|
||||||
SEPARATOR,
|
SEPARATOR,
|
||||||
SelectableDatabase,
|
SelectableDatabase,
|
||||||
} from "./utils"
|
} from "./utils"
|
||||||
|
import * as timers from "../timers"
|
||||||
|
|
||||||
const RETRY_PERIOD_MS = 2000
|
const RETRY_PERIOD_MS = 2000
|
||||||
const STARTUP_TIMEOUT_MS = 5000
|
const STARTUP_TIMEOUT_MS = 5000
|
||||||
|
@ -117,9 +118,9 @@ function waitForConnection(selectDb: number = DEFAULT_SELECT_DB) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// check if the connection is ready
|
// check if the connection is ready
|
||||||
const interval = setInterval(() => {
|
const interval = timers.set(() => {
|
||||||
if (CONNECTED) {
|
if (CONNECTED) {
|
||||||
clearInterval(interval)
|
timers.clear(interval)
|
||||||
resolve("")
|
resolve("")
|
||||||
}
|
}
|
||||||
}, 500)
|
}, 500)
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
export * from "./timers"
|
|
@ -0,0 +1,22 @@
|
||||||
|
let intervals: NodeJS.Timeout[] = []
|
||||||
|
|
||||||
|
export function set(callback: () => any, period: number) {
|
||||||
|
const interval = setInterval(callback, period)
|
||||||
|
intervals.push(interval)
|
||||||
|
return interval
|
||||||
|
}
|
||||||
|
|
||||||
|
export function clear(interval: NodeJS.Timeout) {
|
||||||
|
const idx = intervals.indexOf(interval)
|
||||||
|
if (idx !== -1) {
|
||||||
|
intervals.splice(idx, 1)
|
||||||
|
}
|
||||||
|
clearInterval(interval)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function cleanup() {
|
||||||
|
for (let interval of intervals) {
|
||||||
|
clearInterval(interval)
|
||||||
|
}
|
||||||
|
intervals = []
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
import "./logging"
|
import "./logging"
|
||||||
import env from "../src/environment"
|
import env from "../src/environment"
|
||||||
|
import { cleanup } from "../src/timers"
|
||||||
import { mocks, testContainerUtils } from "./utilities"
|
import { mocks, testContainerUtils } from "./utilities"
|
||||||
|
|
||||||
// must explicitly enable fetch mock
|
// must explicitly enable fetch mock
|
||||||
|
@ -21,3 +22,7 @@ if (!process.env.CI) {
|
||||||
}
|
}
|
||||||
|
|
||||||
testContainerUtils.setupEnv(env)
|
testContainerUtils.setupEnv(env)
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
cleanup()
|
||||||
|
})
|
||||||
|
|
|
@ -24,7 +24,7 @@ describe("/api/applications/:appId/sync", () => {
|
||||||
return rows
|
return rows
|
||||||
}
|
}
|
||||||
|
|
||||||
it("make sure its empty initially", async () => {
|
it("make sure that user metadata is correctly sync'd", async () => {
|
||||||
const rows = await getUserMetadata()
|
const rows = await getUserMetadata()
|
||||||
expect(rows.length).toBe(1)
|
expect(rows.length).toBe(1)
|
||||||
})
|
})
|
||||||
|
|
|
@ -27,7 +27,7 @@ import * as api from "./api"
|
||||||
import * as automations from "./automations"
|
import * as automations from "./automations"
|
||||||
import { Thread } from "./threads"
|
import { Thread } from "./threads"
|
||||||
import * as redis from "./utilities/redis"
|
import * as redis from "./utilities/redis"
|
||||||
import { events, logging, middleware } from "@budibase/backend-core"
|
import { events, logging, middleware, timers } from "@budibase/backend-core"
|
||||||
import { initialise as initialiseWebsockets } from "./websocket"
|
import { initialise as initialiseWebsockets } from "./websocket"
|
||||||
import { startup } from "./startup"
|
import { startup } from "./startup"
|
||||||
const Sentry = require("@sentry/node")
|
const Sentry = require("@sentry/node")
|
||||||
|
@ -84,6 +84,7 @@ server.on("close", async () => {
|
||||||
}
|
}
|
||||||
shuttingDown = true
|
shuttingDown = true
|
||||||
console.log("Server Closed")
|
console.log("Server Closed")
|
||||||
|
timers.cleanup()
|
||||||
await automations.shutdown()
|
await automations.shutdown()
|
||||||
await redis.shutdown()
|
await redis.shutdown()
|
||||||
events.shutdown()
|
events.shutdown()
|
||||||
|
|
|
@ -23,7 +23,7 @@ import { LoopStep, LoopStepType, LoopInput } from "../definitions/automations"
|
||||||
* @returns {object} The inputs object which has had all the various types supported by this function converted to their
|
* @returns {object} The inputs object which has had all the various types supported by this function converted to their
|
||||||
* primitive types.
|
* primitive types.
|
||||||
*/
|
*/
|
||||||
export function cleanInputValues(inputs: Record<string, any>, schema: any) {
|
export function cleanInputValues(inputs: Record<string, any>, schema?: any) {
|
||||||
if (schema == null) {
|
if (schema == null) {
|
||||||
return inputs
|
return inputs
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,84 +0,0 @@
|
||||||
jest.mock("../../threads/automation")
|
|
||||||
jest.mock("../../utilities/redis", () => ({
|
|
||||||
init: jest.fn(),
|
|
||||||
checkTestFlag: () => {
|
|
||||||
return false
|
|
||||||
},
|
|
||||||
}))
|
|
||||||
|
|
||||||
jest.spyOn(global.console, "error")
|
|
||||||
|
|
||||||
require("../../environment")
|
|
||||||
const automation = require("../index")
|
|
||||||
const thread = require("../../threads/automation")
|
|
||||||
const triggers = require("../triggers")
|
|
||||||
const { basicAutomation } = require("../../tests/utilities/structures")
|
|
||||||
const { wait } = require("../../utilities")
|
|
||||||
const { makePartial } = require("../../tests/utilities")
|
|
||||||
const { cleanInputValues } = require("../automationUtils")
|
|
||||||
const setup = require("./utilities")
|
|
||||||
|
|
||||||
describe("Run through some parts of the automations system", () => {
|
|
||||||
let config = setup.getConfig()
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
|
||||||
await automation.init()
|
|
||||||
await config.init()
|
|
||||||
})
|
|
||||||
|
|
||||||
afterAll(setup.afterAll)
|
|
||||||
|
|
||||||
it("should be able to init in builder", async () => {
|
|
||||||
await triggers.externalTrigger(basicAutomation(), { a: 1, appId: config.appId })
|
|
||||||
await wait(100)
|
|
||||||
expect(thread.execute).toHaveBeenCalled()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should check coercion", async () => {
|
|
||||||
const table = await config.createTable()
|
|
||||||
const automation = basicAutomation()
|
|
||||||
automation.definition.trigger.inputs.tableId = table._id
|
|
||||||
automation.definition.trigger.stepId = "APP"
|
|
||||||
automation.definition.trigger.inputs.fields = { a: "number" }
|
|
||||||
await triggers.externalTrigger(automation, {
|
|
||||||
appId: config.getAppId(),
|
|
||||||
fields: {
|
|
||||||
a: "1"
|
|
||||||
}
|
|
||||||
})
|
|
||||||
await wait(100)
|
|
||||||
expect(thread.execute).toHaveBeenCalledWith(makePartial({
|
|
||||||
data: {
|
|
||||||
event: {
|
|
||||||
fields: {
|
|
||||||
a: 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}), expect.any(Function))
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should be able to clean inputs with the utilities", () => {
|
|
||||||
// can't clean without a schema
|
|
||||||
let output = cleanInputValues({a: "1"})
|
|
||||||
expect(output.a).toBe("1")
|
|
||||||
output = cleanInputValues({a: "1", b: "true", c: "false", d: 1, e: "help"}, {
|
|
||||||
properties: {
|
|
||||||
a: {
|
|
||||||
type: "number",
|
|
||||||
},
|
|
||||||
b: {
|
|
||||||
type: "boolean",
|
|
||||||
},
|
|
||||||
c: {
|
|
||||||
type: "boolean",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
expect(output.a).toBe(1)
|
|
||||||
expect(output.b).toBe(true)
|
|
||||||
expect(output.c).toBe(false)
|
|
||||||
expect(output.d).toBe(1)
|
|
||||||
expect(output.e).toBe("help")
|
|
||||||
})
|
|
||||||
})
|
|
|
@ -0,0 +1,99 @@
|
||||||
|
jest.mock("../../threads/automation")
|
||||||
|
jest.mock("../../utilities/redis", () => ({
|
||||||
|
init: jest.fn(),
|
||||||
|
checkTestFlag: () => {
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
|
||||||
|
jest.spyOn(global.console, "error")
|
||||||
|
|
||||||
|
import "../../environment"
|
||||||
|
import * as automation from "../index"
|
||||||
|
import * as thread from "../../threads/automation"
|
||||||
|
import * as triggers from "../triggers"
|
||||||
|
import { basicAutomation } from "../../tests/utilities/structures"
|
||||||
|
import { wait } from "../../utilities"
|
||||||
|
import { makePartial } from "../../tests/utilities"
|
||||||
|
import { cleanInputValues } from "../automationUtils"
|
||||||
|
import * as setup from "./utilities"
|
||||||
|
import { Automation } from "@budibase/types"
|
||||||
|
|
||||||
|
describe("Run through some parts of the automations system", () => {
|
||||||
|
let config = setup.getConfig()
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await automation.init()
|
||||||
|
await config.init()
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await automation.shutdown()
|
||||||
|
setup.afterAll()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should be able to init in builder", async () => {
|
||||||
|
const automation: Automation = {
|
||||||
|
...basicAutomation(),
|
||||||
|
appId: config.appId,
|
||||||
|
}
|
||||||
|
const fields: any = { a: 1, appId: config.appId }
|
||||||
|
await triggers.externalTrigger(automation, fields)
|
||||||
|
await wait(100)
|
||||||
|
expect(thread.execute).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should check coercion", async () => {
|
||||||
|
const table = await config.createTable()
|
||||||
|
const automation: any = basicAutomation()
|
||||||
|
automation.definition.trigger.inputs.tableId = table._id
|
||||||
|
automation.definition.trigger.stepId = "APP"
|
||||||
|
automation.definition.trigger.inputs.fields = { a: "number" }
|
||||||
|
const fields: any = {
|
||||||
|
appId: config.getAppId(),
|
||||||
|
fields: {
|
||||||
|
a: "1",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
await triggers.externalTrigger(automation, fields)
|
||||||
|
await wait(100)
|
||||||
|
expect(thread.execute).toHaveBeenCalledWith(
|
||||||
|
makePartial({
|
||||||
|
data: {
|
||||||
|
event: {
|
||||||
|
fields: {
|
||||||
|
a: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
expect.any(Function)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should be able to clean inputs with the utilities", () => {
|
||||||
|
// can't clean without a schema
|
||||||
|
let output = cleanInputValues({ a: "1" })
|
||||||
|
expect(output.a).toBe("1")
|
||||||
|
output = cleanInputValues(
|
||||||
|
{ a: "1", b: "true", c: "false", d: 1, e: "help" },
|
||||||
|
{
|
||||||
|
properties: {
|
||||||
|
a: {
|
||||||
|
type: "number",
|
||||||
|
},
|
||||||
|
b: {
|
||||||
|
type: "boolean",
|
||||||
|
},
|
||||||
|
c: {
|
||||||
|
type: "boolean",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
expect(output.a).toBe(1)
|
||||||
|
expect(output.b).toBe(true)
|
||||||
|
expect(output.c).toBe(false)
|
||||||
|
expect(output.d).toBe(1)
|
||||||
|
})
|
||||||
|
})
|
|
@ -92,7 +92,7 @@ class RedisIntegration {
|
||||||
}
|
}
|
||||||
|
|
||||||
async disconnect() {
|
async disconnect() {
|
||||||
return this.client.disconnect()
|
return this.client.quit()
|
||||||
}
|
}
|
||||||
|
|
||||||
async redisContext(query: Function) {
|
async redisContext(query: Function) {
|
||||||
|
|
|
@ -39,6 +39,10 @@ describe("Google Sheets Integration", () => {
|
||||||
config.setGoogleAuth("test")
|
config.setGoogleAuth("test")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await config.end()
|
||||||
|
})
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
integration = new GoogleSheetsIntegration.integration({
|
integration = new GoogleSheetsIntegration.integration({
|
||||||
spreadsheetId: "randomId",
|
spreadsheetId: "randomId",
|
||||||
|
|
|
@ -3,17 +3,17 @@ import { default as RedisIntegration } from "../redis"
|
||||||
|
|
||||||
class TestConfiguration {
|
class TestConfiguration {
|
||||||
integration: any
|
integration: any
|
||||||
redis: any
|
|
||||||
|
|
||||||
constructor(config: any = {}) {
|
constructor(config: any = {}) {
|
||||||
this.integration = new RedisIntegration.integration(config)
|
this.integration = new RedisIntegration.integration(config)
|
||||||
this.redis = new Redis({
|
// have to kill the basic integration before replacing it
|
||||||
|
this.integration.client.quit()
|
||||||
|
this.integration.client = new Redis({
|
||||||
data: {
|
data: {
|
||||||
test: "test",
|
test: "test",
|
||||||
result: "1",
|
result: "1",
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
this.integration.client = this.redis
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,13 +24,17 @@ describe("Redis Integration", () => {
|
||||||
config = new TestConfiguration()
|
config = new TestConfiguration()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
config.integration.disconnect()
|
||||||
|
})
|
||||||
|
|
||||||
it("calls the create method with the correct params", async () => {
|
it("calls the create method with the correct params", async () => {
|
||||||
const body = {
|
const body = {
|
||||||
key: "key",
|
key: "key",
|
||||||
value: "value",
|
value: "value",
|
||||||
}
|
}
|
||||||
await config.integration.create(body)
|
await config.integration.create(body)
|
||||||
expect(await config.redis.get("key")).toEqual("value")
|
expect(await config.integration.client.get("key")).toEqual("value")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("calls the read method with the correct params", async () => {
|
it("calls the read method with the correct params", async () => {
|
||||||
|
@ -46,7 +50,7 @@ describe("Redis Integration", () => {
|
||||||
key: "test",
|
key: "test",
|
||||||
}
|
}
|
||||||
await config.integration.delete(body)
|
await config.integration.delete(body)
|
||||||
expect(await config.redis.get(body.key)).toEqual(null)
|
expect(await config.integration.client.get(body.key)).toEqual(null)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("calls the pipeline method with the correct params", async () => {
|
it("calls the pipeline method with the correct params", async () => {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import "./logging"
|
import "./logging"
|
||||||
import env from "../environment"
|
import env from "../environment"
|
||||||
import { env as coreEnv } from "@budibase/backend-core"
|
import { env as coreEnv, timers } from "@budibase/backend-core"
|
||||||
import { testContainerUtils } from "@budibase/backend-core/tests"
|
import { testContainerUtils } from "@budibase/backend-core/tests"
|
||||||
|
|
||||||
if (!process.env.DEBUG) {
|
if (!process.env.DEBUG) {
|
||||||
|
@ -17,3 +17,7 @@ if (!process.env.CI) {
|
||||||
}
|
}
|
||||||
|
|
||||||
testContainerUtils.setupEnv(env, coreEnv)
|
testContainerUtils.setupEnv(env, coreEnv)
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
timers.cleanup()
|
||||||
|
})
|
||||||
|
|
|
@ -165,6 +165,8 @@ class TestConfiguration {
|
||||||
}
|
}
|
||||||
if (this.server) {
|
if (this.server) {
|
||||||
this.server.close()
|
this.server.close()
|
||||||
|
} else {
|
||||||
|
require("../../app").default.close()
|
||||||
}
|
}
|
||||||
if (this.allApps) {
|
if (this.allApps) {
|
||||||
cleanup(this.allApps.map(app => app.appId))
|
cleanup(this.allApps.map(app => app.appId))
|
||||||
|
|
|
@ -106,7 +106,7 @@ export function newAutomation({ steps, trigger }: any = {}) {
|
||||||
return automation
|
return automation
|
||||||
}
|
}
|
||||||
|
|
||||||
export function basicAutomation() {
|
export function basicAutomation(appId?: string) {
|
||||||
return {
|
return {
|
||||||
name: "My Automation",
|
name: "My Automation",
|
||||||
screenId: "kasdkfldsafkl",
|
screenId: "kasdkfldsafkl",
|
||||||
|
@ -114,11 +114,23 @@ export function basicAutomation() {
|
||||||
uiTree: {},
|
uiTree: {},
|
||||||
definition: {
|
definition: {
|
||||||
trigger: {
|
trigger: {
|
||||||
|
stepId: AutomationTriggerStepId.APP,
|
||||||
|
name: "test",
|
||||||
|
tagline: "test",
|
||||||
|
icon: "test",
|
||||||
|
description: "test",
|
||||||
|
type: "trigger",
|
||||||
|
id: "test",
|
||||||
inputs: {},
|
inputs: {},
|
||||||
|
schema: {
|
||||||
|
inputs: {},
|
||||||
|
outputs: {},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
steps: [],
|
steps: [],
|
||||||
},
|
},
|
||||||
type: "automation",
|
type: "automation",
|
||||||
|
appId,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import {
|
||||||
middleware,
|
middleware,
|
||||||
queue,
|
queue,
|
||||||
env as coreEnv,
|
env as coreEnv,
|
||||||
|
timers,
|
||||||
} from "@budibase/backend-core"
|
} from "@budibase/backend-core"
|
||||||
db.init()
|
db.init()
|
||||||
import Koa from "koa"
|
import Koa from "koa"
|
||||||
|
@ -91,6 +92,7 @@ server.on("close", async () => {
|
||||||
}
|
}
|
||||||
shuttingDown = true
|
shuttingDown = true
|
||||||
console.log("Server Closed")
|
console.log("Server Closed")
|
||||||
|
timers.cleanup()
|
||||||
await redis.shutdown()
|
await redis.shutdown()
|
||||||
await events.shutdown()
|
await events.shutdown()
|
||||||
await queue.shutdown()
|
await queue.shutdown()
|
||||||
|
|
|
@ -106,6 +106,8 @@ class TestConfiguration {
|
||||||
async afterAll() {
|
async afterAll() {
|
||||||
if (this.server) {
|
if (this.server) {
|
||||||
await this.server.close()
|
await this.server.close()
|
||||||
|
} else {
|
||||||
|
await require("../index").default.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import "./logging"
|
||||||
|
|
||||||
import { mocks, testContainerUtils } from "@budibase/backend-core/tests"
|
import { mocks, testContainerUtils } from "@budibase/backend-core/tests"
|
||||||
import env from "../environment"
|
import env from "../environment"
|
||||||
import { env as coreEnv } from "@budibase/backend-core"
|
import { env as coreEnv, timers } from "@budibase/backend-core"
|
||||||
|
|
||||||
// must explicitly enable fetch mock
|
// must explicitly enable fetch mock
|
||||||
mocks.fetch.enable()
|
mocks.fetch.enable()
|
||||||
|
@ -21,3 +21,7 @@ if (!process.env.CI) {
|
||||||
}
|
}
|
||||||
|
|
||||||
testContainerUtils.setupEnv(env, coreEnv)
|
testContainerUtils.setupEnv(env, coreEnv)
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
timers.cleanup()
|
||||||
|
})
|
||||||
|
|
Loading…
Reference in New Issue