budibase/packages/server/src/api/routes/tests/oauth2.spec.ts

235 lines
6.9 KiB
TypeScript

import {
OAuth2Config,
OAuth2CredentialsMethod,
PASSWORD_REPLACEMENT,
UpsertOAuth2ConfigRequest,
VirtualDocumentType,
} from "@budibase/types"
import * as setup from "./utilities"
import { generator } from "@budibase/backend-core/tests"
import _ from "lodash/fp"
describe("/oauth2", () => {
let config = setup.getConfig()
function makeOAuth2Config(): UpsertOAuth2ConfigRequest {
return {
name: generator.guid(),
url: generator.url(),
clientId: generator.guid(),
clientSecret: generator.hash(),
method: generator.pickone(Object.values(OAuth2CredentialsMethod)),
}
}
beforeAll(async () => await config.init())
beforeEach(async () => await config.newTenant())
const expectOAuth2ConfigId = expect.stringMatching(
`^${VirtualDocumentType.OAUTH2_CONFIG}_.+$`
)
describe("fetch", () => {
it("returns empty when no oauth are created", async () => {
const response = await config.api.oauth2.fetch()
expect(response).toEqual({
configs: [],
})
})
it("returns all created configs", async () => {
const existingConfigs = []
for (let i = 0; i < 10; i++) {
const oauth2Config = makeOAuth2Config()
const result = await config.api.oauth2.create(oauth2Config)
existingConfigs.push({ ...oauth2Config, id: result.config.id })
}
const response = await config.api.oauth2.fetch()
expect(response.configs).toHaveLength(existingConfigs.length)
expect(response).toEqual({
configs: expect.arrayContaining(
existingConfigs.map(c => ({
id: c.id,
name: c.name,
url: c.url,
clientId: c.clientId,
clientSecret: PASSWORD_REPLACEMENT,
method: c.method,
}))
),
})
})
})
describe("create", () => {
it("can create a new configuration", async () => {
const oauth2Config = makeOAuth2Config()
await config.api.oauth2.create(oauth2Config, { status: 201 })
const response = await config.api.oauth2.fetch()
expect(response).toEqual({
configs: [
{
id: expectOAuth2ConfigId,
name: oauth2Config.name,
url: oauth2Config.url,
clientId: oauth2Config.clientId,
clientSecret: PASSWORD_REPLACEMENT,
method: oauth2Config.method,
},
],
})
})
it("can create multiple configurations", async () => {
const oauth2Config = makeOAuth2Config()
const oauth2Config2 = makeOAuth2Config()
await config.api.oauth2.create(oauth2Config, { status: 201 })
await config.api.oauth2.create(oauth2Config2, { status: 201 })
const response = await config.api.oauth2.fetch()
expect(response.configs).toEqual([
{
id: expectOAuth2ConfigId,
name: oauth2Config.name,
url: oauth2Config.url,
clientId: oauth2Config.clientId,
clientSecret: PASSWORD_REPLACEMENT,
method: oauth2Config.method,
},
{
id: expectOAuth2ConfigId,
name: oauth2Config2.name,
url: oauth2Config2.url,
clientId: oauth2Config2.clientId,
clientSecret: PASSWORD_REPLACEMENT,
method: oauth2Config2.method,
},
])
expect(response.configs[0].id).not.toEqual(response.configs[1].id)
})
it("cannot create configurations with already existing names", async () => {
const oauth2Config = makeOAuth2Config()
const oauth2Config2 = { ...makeOAuth2Config(), name: oauth2Config.name }
await config.api.oauth2.create(oauth2Config, { status: 201 })
await config.api.oauth2.create(oauth2Config2, {
status: 400,
body: {
message: "Name already used",
status: 400,
},
})
const response = await config.api.oauth2.fetch()
expect(response.configs).toEqual([
{
id: expectOAuth2ConfigId,
name: oauth2Config.name,
url: oauth2Config.url,
clientId: oauth2Config.clientId,
clientSecret: PASSWORD_REPLACEMENT,
method: oauth2Config.method,
},
])
})
})
describe("update", () => {
let existingConfigs: OAuth2Config[] = []
beforeEach(async () => {
existingConfigs = []
for (let i = 0; i < 10; i++) {
const oauth2Config = makeOAuth2Config()
const result = await config.api.oauth2.create(oauth2Config)
existingConfigs.push({ ...oauth2Config, id: result.config.id })
}
})
it("can update an existing configuration", async () => {
const { id: configId, ...configData } = _.sample(existingConfigs)!
await config.api.oauth2.update(configId, {
...configData,
name: "updated name",
})
const response = await config.api.oauth2.fetch()
expect(response.configs).toHaveLength(existingConfigs.length)
expect(response.configs).toEqual(
expect.arrayContaining([
{
id: configId,
name: "updated name",
url: configData.url,
clientId: configData.clientId,
clientSecret: PASSWORD_REPLACEMENT,
method: configData.method,
},
])
)
})
it("throw if config not found", async () => {
await config.api.oauth2.update("unexisting", makeOAuth2Config(), {
status: 404,
body: { message: "OAuth2 config with id 'unexisting' not found." },
})
})
it("throws if trying to use an existing name", async () => {
const [config1, config2] = _.sampleSize(2, existingConfigs)
const { id: configId, ...configData } = config1
await config.api.oauth2.update(
configId,
{
...configData,
name: config2.name,
},
{
status: 400,
body: {
message: `OAuth2 config with name '${config2.name}' is already taken.`,
},
}
)
})
})
describe("delete", () => {
let existingConfigs: OAuth2Config[] = []
beforeEach(async () => {
existingConfigs = []
for (let i = 0; i < 5; i++) {
const oauth2Config = makeOAuth2Config()
const result = await config.api.oauth2.create(oauth2Config)
existingConfigs.push({ ...oauth2Config, id: result.config.id })
}
})
it("can delete an existing configuration", async () => {
const { id: configId } = _.sample(existingConfigs)!
await config.api.oauth2.delete(configId, { status: 204 })
const response = await config.api.oauth2.fetch()
expect(response.configs).toHaveLength(existingConfigs.length - 1)
expect(response.configs.find(c => c.id === configId)).toBeUndefined()
})
it("throw if config not found", async () => {
await config.api.oauth2.delete("unexisting", {
status: 404,
body: { message: "OAuth2 config with id 'unexisting' not found." },
})
})
})
})