Typing and config.api'ing application.spec.ts, WIP
This commit is contained in:
parent
f417c2d8a4
commit
b2c4f04aa6
|
@ -47,6 +47,7 @@ import {
|
|||
PlanType,
|
||||
Screen,
|
||||
UserCtx,
|
||||
CreateAppRequest,
|
||||
} from "@budibase/types"
|
||||
import { BASE_LAYOUT_PROP_IDS } from "../../constants/layouts"
|
||||
import sdk from "../../sdk"
|
||||
|
@ -116,8 +117,8 @@ function checkAppName(
|
|||
}
|
||||
|
||||
interface AppTemplate {
|
||||
templateString: string
|
||||
useTemplate: string
|
||||
templateString?: string
|
||||
useTemplate?: string
|
||||
file?: {
|
||||
type: string
|
||||
path: string
|
||||
|
@ -231,17 +232,21 @@ export async function fetchAppPackage(ctx: UserCtx) {
|
|||
}
|
||||
}
|
||||
|
||||
async function performAppCreate(ctx: UserCtx) {
|
||||
async function performAppCreate(ctx: UserCtx<CreateAppRequest, App>) {
|
||||
const apps = (await dbCore.getAllApps({ dev: true })) as App[]
|
||||
const name = ctx.request.body.name,
|
||||
possibleUrl = ctx.request.body.url,
|
||||
encryptionPassword = ctx.request.body.encryptionPassword
|
||||
const {
|
||||
name,
|
||||
url,
|
||||
encryptionPassword,
|
||||
useTemplate,
|
||||
templateKey,
|
||||
templateString,
|
||||
} = ctx.request.body
|
||||
|
||||
checkAppName(ctx, apps, name)
|
||||
const url = sdk.applications.getAppUrl({ name, url: possibleUrl })
|
||||
checkAppUrl(ctx, apps, url)
|
||||
const appUrl = sdk.applications.getAppUrl({ name, url })
|
||||
checkAppUrl(ctx, apps, appUrl)
|
||||
|
||||
const { useTemplate, templateKey, templateString } = ctx.request.body
|
||||
const instanceConfig: AppTemplate = {
|
||||
useTemplate,
|
||||
key: templateKey,
|
||||
|
@ -268,7 +273,7 @@ async function performAppCreate(ctx: UserCtx) {
|
|||
version: envCore.VERSION,
|
||||
componentLibraries: ["@budibase/standard-components"],
|
||||
name: name,
|
||||
url: url,
|
||||
url: appUrl,
|
||||
template: templateKey,
|
||||
instance,
|
||||
tenantId: tenancy.getTenantId(),
|
||||
|
|
|
@ -35,41 +35,30 @@ describe("/applications", () => {
|
|||
|
||||
describe("create", () => {
|
||||
it("creates empty app", async () => {
|
||||
const res = await request
|
||||
.post("/api/applications")
|
||||
.field("name", utils.newid())
|
||||
.set(config.defaultHeaders())
|
||||
.expect("Content-Type", /json/)
|
||||
.expect(200)
|
||||
expect(res.body._id).toBeDefined()
|
||||
const app = await config.api.application.create({ name: utils.newid() })
|
||||
expect(app._id).toBeDefined()
|
||||
expect(events.app.created).toBeCalledTimes(1)
|
||||
})
|
||||
|
||||
it("creates app from template", async () => {
|
||||
const res = await request
|
||||
.post("/api/applications")
|
||||
.field("name", utils.newid())
|
||||
.field("useTemplate", "true")
|
||||
.field("templateKey", "test")
|
||||
.field("templateString", "{}") // override the file download
|
||||
.set(config.defaultHeaders())
|
||||
.expect("Content-Type", /json/)
|
||||
.expect(200)
|
||||
expect(res.body._id).toBeDefined()
|
||||
const app = await config.api.application.create({
|
||||
name: utils.newid(),
|
||||
useTemplate: "true",
|
||||
templateKey: "test",
|
||||
templateString: "{}",
|
||||
})
|
||||
expect(app._id).toBeDefined()
|
||||
expect(events.app.created).toBeCalledTimes(1)
|
||||
expect(events.app.templateImported).toBeCalledTimes(1)
|
||||
})
|
||||
|
||||
it("creates app from file", async () => {
|
||||
const res = await request
|
||||
.post("/api/applications")
|
||||
.field("name", utils.newid())
|
||||
.field("useTemplate", "true")
|
||||
.set(config.defaultHeaders())
|
||||
.attach("templateFile", "src/api/routes/tests/data/export.txt")
|
||||
.expect("Content-Type", /json/)
|
||||
.expect(200)
|
||||
expect(res.body._id).toBeDefined()
|
||||
const app = await config.api.application.create({
|
||||
name: utils.newid(),
|
||||
useTemplate: "true",
|
||||
templateFile: "src/api/routes/tests/data/export.txt",
|
||||
})
|
||||
expect(app._id).toBeDefined()
|
||||
expect(events.app.created).toBeCalledTimes(1)
|
||||
expect(events.app.fileImported).toBeCalledTimes(1)
|
||||
})
|
||||
|
@ -84,24 +73,21 @@ describe("/applications", () => {
|
|||
})
|
||||
|
||||
it("migrates navigation settings from old apps", async () => {
|
||||
const res = await request
|
||||
.post("/api/applications")
|
||||
.field("name", "Old App")
|
||||
.field("useTemplate", "true")
|
||||
.set(config.defaultHeaders())
|
||||
.attach("templateFile", "src/api/routes/tests/data/old-app.txt")
|
||||
.expect("Content-Type", /json/)
|
||||
.expect(200)
|
||||
expect(res.body._id).toBeDefined()
|
||||
expect(res.body.navigation).toBeDefined()
|
||||
expect(res.body.navigation.hideLogo).toBe(true)
|
||||
expect(res.body.navigation.title).toBe("Custom Title")
|
||||
expect(res.body.navigation.hideLogo).toBe(true)
|
||||
expect(res.body.navigation.navigation).toBe("Left")
|
||||
expect(res.body.navigation.navBackground).toBe(
|
||||
const app = await config.api.application.create({
|
||||
name: "Old App",
|
||||
useTemplate: "true",
|
||||
templateFile: "src/api/routes/tests/data/old-app.txt",
|
||||
})
|
||||
expect(app._id).toBeDefined()
|
||||
expect(app.navigation).toBeDefined()
|
||||
expect(app.navigation!.hideLogo).toBe(true)
|
||||
expect(app.navigation!.title).toBe("Custom Title")
|
||||
expect(app.navigation!.hideLogo).toBe(true)
|
||||
expect(app.navigation!.navigation).toBe("Left")
|
||||
expect(app.navigation!.navBackground).toBe(
|
||||
"var(--spectrum-global-color-blue-600)"
|
||||
)
|
||||
expect(res.body.navigation.navTextColor).toBe(
|
||||
expect(app.navigation!.navTextColor).toBe(
|
||||
"var(--spectrum-global-color-gray-50)"
|
||||
)
|
||||
expect(events.app.created).toBeCalledTimes(1)
|
||||
|
@ -118,15 +104,10 @@ describe("/applications", () => {
|
|||
it("lists all applications", async () => {
|
||||
await config.createApp("app1")
|
||||
await config.createApp("app2")
|
||||
|
||||
const res = await request
|
||||
.get(`/api/applications?status=${AppStatus.DEV}`)
|
||||
.set(config.defaultHeaders())
|
||||
.expect("Content-Type", /json/)
|
||||
.expect(200)
|
||||
const apps = await config.api.application.fetch({ status: AppStatus.DEV })
|
||||
|
||||
// two created apps + the inited app
|
||||
expect(res.body.length).toBe(3)
|
||||
expect(apps.length).toBe(3)
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
@ -1,13 +1,38 @@
|
|||
import { Response } from "supertest"
|
||||
import { App } from "@budibase/types"
|
||||
import { App, type CreateAppRequest } from "@budibase/types"
|
||||
import TestConfiguration from "../TestConfiguration"
|
||||
import { TestAPI } from "./base"
|
||||
import { AppStatus } from "../../../db/utils"
|
||||
import { dbObjectAsPojo } from "oracledb"
|
||||
|
||||
export class ApplicationAPI extends TestAPI {
|
||||
constructor(config: TestConfiguration) {
|
||||
super(config)
|
||||
}
|
||||
|
||||
create = async (app: CreateAppRequest): Promise<App> => {
|
||||
const request = this.request
|
||||
.post("/api/applications")
|
||||
.set(this.config.defaultHeaders())
|
||||
.expect("Content-Type", /json/)
|
||||
|
||||
for (const key of Object.keys(app)) {
|
||||
request.field(key, (app as any)[key])
|
||||
}
|
||||
|
||||
if (app.templateFile) {
|
||||
request.attach("templateFile", app.templateFile)
|
||||
}
|
||||
|
||||
const result = await request
|
||||
|
||||
if (result.statusCode !== 200) {
|
||||
fail(JSON.stringify(result.body))
|
||||
}
|
||||
|
||||
return result.body as App
|
||||
}
|
||||
|
||||
getRaw = async (appId: string): Promise<Response> => {
|
||||
const result = await this.request
|
||||
.get(`/api/applications/${appId}/appPackage`)
|
||||
|
@ -21,4 +46,18 @@ export class ApplicationAPI extends TestAPI {
|
|||
const result = await this.getRaw(appId)
|
||||
return result.body.application as App
|
||||
}
|
||||
|
||||
fetch = async ({ status }: { status?: AppStatus } = {}): Promise<App[]> => {
|
||||
let query = []
|
||||
if (status) {
|
||||
query.push(`status=${status}`)
|
||||
}
|
||||
|
||||
const result = await this.request
|
||||
.get(`/api/applications${query.length ? `?${query.join("&")}` : ""}`)
|
||||
.set(this.config.defaultHeaders())
|
||||
.expect("Content-Type", /json/)
|
||||
.expect(200)
|
||||
return result.body as App[]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,3 +73,15 @@ export interface AppFeatures {
|
|||
export interface AutomationSettings {
|
||||
chainAutomations?: boolean
|
||||
}
|
||||
|
||||
export interface CreateAppRequest {
|
||||
name: string
|
||||
url?: string
|
||||
useTemplate?: string
|
||||
templateName?: string
|
||||
templateKey?: string
|
||||
templateFile?: string
|
||||
includeSampleData?: boolean
|
||||
encryptionPassword?: string
|
||||
templateString?: string
|
||||
}
|
||||
|
|
|
@ -4,10 +4,10 @@ set -e
|
|||
if [[ -n $CI ]]
|
||||
then
|
||||
# Running in ci, where resources are limited
|
||||
echo "jest --coverage --maxWorkers=2 --forceExit --bail"
|
||||
jest --coverage --maxWorkers=2 --forceExit --bail
|
||||
echo "jest --coverage --maxWorkers=2 --forceExit --bail $@"
|
||||
jest --coverage --maxWorkers=2 --forceExit --bail $@
|
||||
else
|
||||
# --maxWorkers performs better in development
|
||||
echo "jest --coverage --maxWorkers=2 --forceExit"
|
||||
jest --coverage --maxWorkers=2 --forceExit
|
||||
echo "jest --coverage --maxWorkers=2 --forceExit $@"
|
||||
jest --coverage --maxWorkers=2 --forceExit $@
|
||||
fi
|
|
@ -1,11 +1,10 @@
|
|||
import { App } from "@budibase/types"
|
||||
import { App, CreateAppRequest } from "@budibase/types"
|
||||
import { Response } from "node-fetch"
|
||||
import {
|
||||
RouteConfig,
|
||||
AppPackageResponse,
|
||||
DeployConfig,
|
||||
MessageResponse,
|
||||
CreateAppRequest,
|
||||
} from "../../../types"
|
||||
import BudibaseInternalAPIClient from "../BudibaseInternalAPIClient"
|
||||
import BaseAPI from "./BaseAPI"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { generator } from "../../shared"
|
||||
import { CreateAppRequest } from "../../types"
|
||||
import { CreateAppRequest } from "@budibase/types"
|
||||
|
||||
function uniqueWord() {
|
||||
return generator.word() + generator.hash()
|
||||
|
|
|
@ -13,17 +13,6 @@ describe("Internal API - Table Operations", () => {
|
|||
await config.afterAll()
|
||||
})
|
||||
|
||||
async function createAppFromTemplate() {
|
||||
return config.api.apps.create({
|
||||
name: generator.word(),
|
||||
url: `/${generator.word()}`,
|
||||
useTemplate: "true",
|
||||
templateName: "Near Miss Register",
|
||||
templateKey: "app/near-miss-register",
|
||||
templateFile: undefined,
|
||||
})
|
||||
}
|
||||
|
||||
it("Create and delete table, columns and rows", async () => {
|
||||
// create the app
|
||||
await config.createApp(fixtures.apps.appFromTemplate())
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { BudibaseInternalAPI } from "../internal-api"
|
||||
import { AccountInternalAPI } from "../account-api"
|
||||
import { APIRequestOpts, CreateAppRequest, State } from "../types"
|
||||
import { APIRequestOpts, State } from "../types"
|
||||
import * as fixtures from "../internal-api/fixtures"
|
||||
import { CreateAccountRequest } from "@budibase/types"
|
||||
import { CreateAccountRequest, CreateAppRequest } from "@budibase/types"
|
||||
|
||||
export default class BudibaseTestConfiguration {
|
||||
// apis
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
// TODO: Integrate with budibase
|
||||
export interface CreateAppRequest {
|
||||
name: string
|
||||
url: string
|
||||
useTemplate?: string
|
||||
templateName?: string
|
||||
templateKey?: string
|
||||
templateFile?: string
|
||||
includeSampleData?: boolean
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
export * from "./api"
|
||||
export * from "./apiKeyResponse"
|
||||
export * from "./app"
|
||||
export * from "./appPackage"
|
||||
export * from "./deploy"
|
||||
export * from "./newAccount"
|
||||
|
|
Loading…
Reference in New Issue