Files
2026-07-13 13:34:48 +08:00

229 lines
8.6 KiB
TypeScript

import { Client } from '@botpress/client'
import * as fs from 'fs'
import pathlib from 'path'
import impl from '../../src'
import { ApiIntegration, fetchAllIntegrations, ApiPlugin, fetchAllPlugins } from '../api'
import defaults from '../defaults'
import * as retry from '../retry'
import { Test } from '../typings'
import * as utils from '../utils'
const fetchIntegration = async (client: Client, integrationName: string): Promise<ApiIntegration | undefined> => {
const integrations = await fetchAllIntegrations(client)
return integrations.find(({ name }) => name === integrationName)
}
const fetchPlugin = async (client: Client, pluginName: string): Promise<ApiPlugin | undefined> => {
const plugins = await fetchAllPlugins(client)
return plugins.find(({ name }) => name === pluginName)
}
export const prependWorkspaceHandleIntegration: Test = {
name: 'cli should automatically preprend the workspace handle to the integration name when deploying',
handler: async ({ tmpDir, dependencies, workspaceHandle, logger, ...creds }) => {
const botpressHomeDir = pathlib.join(tmpDir, '.botpresshome')
const baseDir = pathlib.join(tmpDir, 'integrations')
const integrationSuffix = utils.getUUID()
const integrationName = `myintegration${integrationSuffix}`
const integrationNameWithHandle = `${workspaceHandle}/${integrationName}`
const integrationDirName = integrationName
const integrationDir = pathlib.join(baseDir, integrationDirName)
const argv = {
...defaults,
botpressHome: botpressHomeDir,
confirm: true,
...creds,
}
const client = new Client({
apiUrl: creds.apiUrl,
token: creds.token,
workspaceId: creds.workspaceId,
retry: retry.config,
})
await impl
.init({ ...argv, workDir: baseDir, name: integrationNameWithHandle, type: 'integration', template: 'empty' })
.then(utils.handleExitCode)
// Remove handle from package.json:
const pkgJsonPath = pathlib.join(integrationDir, 'package.json')
const pkgJson = await fs.promises.readFile(pkgJsonPath, 'utf-8').then(JSON.parse)
pkgJson.name = pkgJson.name.slice(workspaceHandle.length + 1)
await fs.promises.writeFile(pkgJsonPath, JSON.stringify(pkgJson, null, 2))
await utils.fixBotpressDependencies({ workDir: integrationDir, target: dependencies })
await utils.npmInstall({ workDir: integrationDir }).then(utils.handleExitCode)
await impl.build({ ...argv, workDir: integrationDir }).then(utils.handleExitCode)
await impl.login({ ...argv }).then(utils.handleExitCode)
await impl
.deploy({ ...argv, createNewBot: undefined, botId: undefined, workDir: integrationDir })
.then(utils.handleExitCode)
logger.debug(`Fetching integration "${integrationName}"`)
let integration = await fetchIntegration(client, integrationName)
if (integration) {
throw new Error(`Integration ${integrationName} should not have been created`)
}
const expectedIntegrationName = `${workspaceHandle}/${integrationName}`
logger.debug(`Fetching integration "${expectedIntegrationName}"`)
integration = await fetchIntegration(client, expectedIntegrationName)
if (!integration) {
throw new Error(`Integration ${expectedIntegrationName} should have been created`)
}
logger.debug(`Deleting integration "${integrationName}"`)
await impl.integrations.delete({ ...argv, integrationRef: integration.id }).then(({ exitCode }) => {
exitCode !== 0 && logger.warn(`Failed to delete integration "${integrationName}"`) // not enough to fail the test
})
},
}
export const prependWorkspaceHandlePlugin: Test = {
name: 'cli should automatically prepend the workspace handle to the plugin name when deploying',
handler: async ({ tmpDir, dependencies, workspaceHandle, logger, ...creds }) => {
const botpressHomeDir = pathlib.join(tmpDir, '.botpresshome')
const baseDir = pathlib.join(tmpDir, 'plugins')
const pluginSuffix = utils.getUUID()
const pluginName = `myplugin${pluginSuffix}`
const pluginNameWithHandle = `${workspaceHandle}/${pluginName}`
const pluginDir = pathlib.join(baseDir, pluginName)
const argv = {
...defaults,
botpressHome: botpressHomeDir,
confirm: true,
...creds,
}
const client = new Client({
apiUrl: creds.apiUrl,
token: creds.token,
workspaceId: creds.workspaceId,
retry: retry.config,
})
await impl
.init({ ...argv, workDir: baseDir, name: pluginNameWithHandle, type: 'plugin', template: 'empty' })
.then(utils.handleExitCode)
// Remove handle from package.json pluginName field:
const pkgJsonPath = pathlib.join(pluginDir, 'package.json')
const pkgJson = await fs.promises.readFile(pkgJsonPath, 'utf-8').then(JSON.parse)
pkgJson.pluginName = pluginName
await fs.promises.writeFile(pkgJsonPath, JSON.stringify(pkgJson, null, 2))
await utils.fixBotpressDependencies({ workDir: pluginDir, target: dependencies })
await utils.npmInstall({ workDir: pluginDir }).then(utils.handleExitCode)
await impl.build({ ...argv, workDir: pluginDir }).then(utils.handleExitCode)
await impl.login({ ...argv }).then(utils.handleExitCode)
await impl
.deploy({ ...argv, createNewBot: undefined, botId: undefined, workDir: pluginDir })
.then(utils.handleExitCode)
logger.debug(`Fetching plugin "${pluginName}"`)
let plugin = await fetchPlugin(client, pluginName)
if (plugin) {
throw new Error(`Plugin ${pluginName} should not have been created without handle prefix`)
}
const expectedPluginName = `${workspaceHandle}/${pluginName}`
logger.debug(`Fetching plugin "${expectedPluginName}"`)
plugin = await fetchPlugin(client, expectedPluginName)
if (!plugin) {
throw new Error(`Plugin ${expectedPluginName} should have been created`)
}
logger.debug(`Deleting plugin "${expectedPluginName}"`)
await impl.plugins.delete({ ...argv, pluginRef: plugin.id }).then(({ exitCode }) => {
exitCode !== 0 && logger.warn(`Failed to delete plugin "${expectedPluginName}"`)
})
},
}
export const enforceWorkspaceHandleIntegration: Test = {
name: 'cli should fail when attempting to deploy an integration with incorrect workspace handle',
handler: async ({ tmpDir, dependencies, ...creds }) => {
const botpressHomeDir = pathlib.join(tmpDir, '.botpresshome')
const baseDir = pathlib.join(tmpDir, 'integrations')
const randomSuffix = utils.getUUID().slice(0, 8)
const name = 'myintegration'
const handle = `myhandle${randomSuffix}`
const integrationName = `${handle}/${name}`
const integrationDir = pathlib.join(baseDir, name)
const argv = {
...defaults,
botpressHome: botpressHomeDir,
confirm: true,
...creds,
}
await impl
.init({ ...argv, workDir: baseDir, name: integrationName, type: 'integration', template: 'empty' })
.then(utils.handleExitCode)
await utils.fixBotpressDependencies({ workDir: integrationDir, target: dependencies })
await utils.npmInstall({ workDir: integrationDir }).then(utils.handleExitCode)
await impl.login({ ...argv }).then(utils.handleExitCode)
const { exitCode } = await impl.deploy({
...argv,
createNewBot: undefined,
botId: undefined,
workDir: integrationDir,
})
if (exitCode === 0) {
throw new Error(`Integration ${integrationName} should not have been deployed`)
}
},
}
export const enforceWorkspaceHandlePlugin: Test = {
name: 'cli should fail when attempting to deploy a plugin with incorrect workspace handle',
handler: async ({ tmpDir, dependencies, ...creds }) => {
const botpressHomeDir = pathlib.join(tmpDir, '.botpresshome')
const baseDir = pathlib.join(tmpDir, 'plugins')
const randomSuffix = utils.getUUID().slice(0, 8)
const name = 'myplugin'
const handle = `myhandle${randomSuffix}`
const pluginName = `${handle}/${name}`
const pluginDir = pathlib.join(baseDir, name)
const argv = {
...defaults,
botpressHome: botpressHomeDir,
confirm: true,
...creds,
}
await impl
.init({ ...argv, workDir: baseDir, name: pluginName, type: 'plugin', template: 'empty' })
.then(utils.handleExitCode)
await utils.fixBotpressDependencies({ workDir: pluginDir, target: dependencies })
await utils.npmInstall({ workDir: pluginDir }).then(utils.handleExitCode)
await impl.login({ ...argv }).then(utils.handleExitCode)
const { exitCode } = await impl.deploy({
...argv,
createNewBot: undefined,
botId: undefined,
workDir: pluginDir,
})
if (exitCode === 0) {
throw new Error(`Plugin ${pluginName} should not have been deployed`)
}
},
}