Restructure account tests to test signup and deletion as a single flow
This commit is contained in:
parent
944b6e0baa
commit
4dc558d3e9
|
@ -1,6 +1,8 @@
|
|||
import { Response } from "node-fetch"
|
||||
import env from "../../environment"
|
||||
import fetch, { HeadersInit } from "node-fetch"
|
||||
import { State } from "../../types"
|
||||
import { Header } from "@budibase/backend-core"
|
||||
|
||||
type APIMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE"
|
||||
|
||||
|
@ -28,7 +30,7 @@ export default class AccountInternalAPIClient {
|
|||
|
||||
apiCall =
|
||||
(method: APIMethod) =>
|
||||
async (url = "", options: ApiOptions = {}) => {
|
||||
async (url = "", options: ApiOptions = {}): Promise<[Response, any]> => {
|
||||
const requestOptions = {
|
||||
method,
|
||||
body: JSON.stringify(options.body),
|
||||
|
@ -46,7 +48,7 @@ export default class AccountInternalAPIClient {
|
|||
if (options.internal) {
|
||||
requestOptions.headers = {
|
||||
...requestOptions.headers,
|
||||
...{ "x-budibase-api-key": env.ACCOUNT_PORTAL_API_KEY },
|
||||
...{ [Header.API_KEY] : env.ACCOUNT_PORTAL_API_KEY },
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { generator } from "../../shared"
|
||||
import { Hosting, CreateAccountRequest } from "@budibase/types"
|
||||
|
||||
// TODO: Refactor me to central location
|
||||
export const generateAccount = (): CreateAccountRequest => {
|
||||
const uuid = generator.guid()
|
||||
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
import TestConfiguration from "../../config/TestConfiguration"
|
||||
import * as fixtures from "../../fixtures"
|
||||
import { generator } from "../../../shared"
|
||||
|
||||
describe("Account Internal Operations", () => {
|
||||
const config = new TestConfiguration()
|
||||
|
||||
beforeAll(async () => {
|
||||
await config.beforeAll()
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
await config.afterAll()
|
||||
})
|
||||
|
||||
it("performs account deletion", async () => {
|
||||
// Deleting by unknown id doesn't work
|
||||
const accountId = generator.string()
|
||||
await config.api.accounts.delete(accountId, { status: 404 })
|
||||
|
||||
// Create new account
|
||||
const [_, account] = await config.api.accounts.create({
|
||||
...fixtures.accounts.generateAccount(),
|
||||
})
|
||||
|
||||
// New account can be deleted
|
||||
await config.api.accounts.delete(account.accountId)
|
||||
})
|
||||
})
|
|
@ -0,0 +1,80 @@
|
|||
import TestConfiguration from "../../config/TestConfiguration"
|
||||
import * as fixtures from "../../fixtures"
|
||||
import { generator } from "../../../shared"
|
||||
|
||||
describe("accounts", () => {
|
||||
const config = new TestConfiguration()
|
||||
|
||||
beforeAll(async () => {
|
||||
await config.beforeAll()
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
await config.afterAll()
|
||||
})
|
||||
|
||||
it("performs signup and deletion flow", async () => {
|
||||
await config.doInNewState(async () => {
|
||||
const createAccountRequest = fixtures.accounts.generateAccount()
|
||||
const email = createAccountRequest.email
|
||||
const tenantId = createAccountRequest.tenantId
|
||||
|
||||
// Validation - email and tenant id allowed
|
||||
await config.api.accounts.validateEmail(email)
|
||||
await config.api.accounts.validateTenantId(tenantId)
|
||||
|
||||
// Create unverified account
|
||||
await config.api.accounts.create(createAccountRequest)
|
||||
|
||||
// Validation - email and tenant id no longer valid
|
||||
await config.api.accounts.validateEmail(email, { status: 400 })
|
||||
await config.api.accounts.validateTenantId(tenantId, { status: 400 })
|
||||
|
||||
// Attempt to log in using unverified account
|
||||
await config.loginAsAccount(createAccountRequest, { status: 400 })
|
||||
|
||||
// Re-send verification email to get access to code
|
||||
const [_, code] = await config.accountsApi.accounts.sendVerificationEmail(email)
|
||||
|
||||
// Send the verification request
|
||||
await config.accountsApi.accounts.verifyAccount(code!)
|
||||
|
||||
// Can now login to the account
|
||||
await config.loginAsAccount(createAccountRequest)
|
||||
|
||||
// Delete account
|
||||
await config.api.accounts.deleteCurrentAccount()
|
||||
|
||||
// Can't login
|
||||
await config.loginAsAccount(createAccountRequest, { status: 403 })
|
||||
})
|
||||
})
|
||||
|
||||
describe("searching accounts", () => {
|
||||
it("searches by tenant id", async () => {
|
||||
const tenantId = generator.string()
|
||||
|
||||
// empty result
|
||||
const [emptyRes, emptyBody] = await config.api.accounts.search(tenantId, "tenantId")
|
||||
expect(emptyBody.length).toBe(0)
|
||||
|
||||
// hit result
|
||||
const [hitRes, hitBody] = await config.api.accounts.search(config.state.tenantId!, "tenantId")
|
||||
expect(hitBody.length).toBe(1)
|
||||
expect(hitBody[0].tenantId).toBe(config.state.tenantId)
|
||||
})
|
||||
|
||||
it("searches by email", async () => {
|
||||
const email = generator.email()
|
||||
|
||||
// empty result
|
||||
const [emptyRes, emptyBody] = await config.api.accounts.search(email, "email")
|
||||
expect(emptyBody.length).toBe(0)
|
||||
|
||||
// hit result
|
||||
const [hitRes, hitBody] = await config.api.accounts.search(config.state.email!, "email")
|
||||
expect(hitBody.length).toBe(1)
|
||||
expect(hitBody[0].email).toBe(config.state.email)
|
||||
})
|
||||
})
|
||||
})
|
|
@ -1,23 +0,0 @@
|
|||
import TestConfiguration from "../../config/TestConfiguration"
|
||||
import * as fixtures from "../../fixtures"
|
||||
|
||||
describe("Account API - Create Account", () => {
|
||||
const config = new TestConfiguration()
|
||||
|
||||
beforeAll(async () => {
|
||||
await config.beforeAll()
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
await config.afterAll()
|
||||
})
|
||||
|
||||
describe("POST /api/accounts/", () => {
|
||||
it("Returns 201", async () => {
|
||||
const [res, account] = await config.api.accounts.create({
|
||||
...fixtures.accounts.generateAccount()
|
||||
})
|
||||
expect(res.status).toBe(201)
|
||||
})
|
||||
})
|
||||
})
|
|
@ -1,52 +0,0 @@
|
|||
import TestConfiguration from "../../config/TestConfiguration"
|
||||
import * as fixtures from "../../fixtures"
|
||||
import { generator } from "../../../shared"
|
||||
|
||||
describe("Account API - Delete Account", () => {
|
||||
const config = new TestConfiguration()
|
||||
|
||||
beforeAll(async () => {
|
||||
await config.beforeAll()
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
await config.afterAll()
|
||||
})
|
||||
|
||||
describe("DEL /api/accounts", () => {
|
||||
it("Returns 204", async () => {
|
||||
await config.doInNewState(async () => {
|
||||
// Create account
|
||||
const createAccountRequest = fixtures.accounts.generateAccount()
|
||||
await config.api.accounts.create(createAccountRequest)
|
||||
|
||||
// Login - Get cookie
|
||||
await config.login(
|
||||
createAccountRequest.email,
|
||||
createAccountRequest.password,
|
||||
createAccountRequest.tenantId
|
||||
)
|
||||
|
||||
// Delete account
|
||||
const res = await config.api.accounts.deleteCurrentAccount()
|
||||
expect(res.status).toBe(204)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("DEL /api/accounts/{accountId}", () => {
|
||||
it("Returns 204", async () => {
|
||||
const [response, account] = await config.api.accounts.create({
|
||||
...fixtures.accounts.generateAccount()
|
||||
})
|
||||
// Delete account by ID
|
||||
const res = await config.api.accounts.delete(account.accountId)
|
||||
expect(res.status).toBe(204)
|
||||
})
|
||||
|
||||
it("returns 404 - Account not found", async () => {
|
||||
const accountId = generator.string()
|
||||
await config.api.accounts.delete(accountId, {status:404})
|
||||
})
|
||||
})
|
||||
})
|
|
@ -1,70 +0,0 @@
|
|||
import TestConfiguration from "../../config/TestConfiguration"
|
||||
import { generator } from "../../../shared"
|
||||
|
||||
describe("Account API - Search for Account", () => {
|
||||
const config = new TestConfiguration()
|
||||
|
||||
beforeAll(async () => {
|
||||
await config.beforeAll()
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
await config.afterAll()
|
||||
})
|
||||
|
||||
describe("POST /api/accounts/search", () => {
|
||||
describe("by tenant", () => {
|
||||
it("returns 200 + empty", async () => {
|
||||
const tenantId = generator.string()
|
||||
const [res, body] =
|
||||
await config.api.accounts.search(tenantId, "tenantId")
|
||||
expect(res.status).toBe(200)
|
||||
expect(body.length).toBe(0)
|
||||
})
|
||||
|
||||
it("returns 200 + found", async () => {
|
||||
const [res, body] =
|
||||
await config.api.accounts.search(config.state.tenantId!, "tenantId")
|
||||
expect(res.status).toBe(200)
|
||||
expect(body.length).toBe(1)
|
||||
expect(body[0].tenantId).toBe(config.state.tenantId)
|
||||
})
|
||||
|
||||
it("returns 400 + error: Invalid body - tenantId is not allowed to be empty", async () => {
|
||||
const [res, body] =
|
||||
await config.api.accounts.search("", "tenantId")
|
||||
expect(body).toEqual({
|
||||
message: "Invalid body - \"tenantId\" is not allowed to be empty",
|
||||
status: 400
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("by email", () => {
|
||||
it("returns 200 + empty", async () => {
|
||||
const email = generator.email()
|
||||
const [res, body] =
|
||||
await config.api.accounts.search(email, "email")
|
||||
expect(res.status).toBe(200)
|
||||
expect(body.length).toBe(0)
|
||||
})
|
||||
|
||||
it("returns 200 + found", async () => {
|
||||
const [res, body] =
|
||||
await config.api.accounts.search(config.state.email!, "email")
|
||||
expect(res.status).toBe(200)
|
||||
expect(body.length).toBe(1)
|
||||
expect(body[0].email).toBe(config.state.email)
|
||||
})
|
||||
|
||||
it("returns 400 + error: Invalid body - email is not allowed to be empty", async () => {
|
||||
const [res, body] =
|
||||
await config.api.accounts.search("", "email")
|
||||
expect(body).toEqual({
|
||||
message: "Invalid body - \"email\" is not allowed to be empty",
|
||||
status: 400
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
|
@ -1,46 +0,0 @@
|
|||
import TestConfiguration from "../../config/TestConfiguration"
|
||||
import * as fixtures from "../../fixtures"
|
||||
import { generator } from "../../../shared"
|
||||
|
||||
describe("Account API - Validate Account", () => {
|
||||
const config = new TestConfiguration()
|
||||
|
||||
beforeAll(async () => {
|
||||
await config.beforeAll()
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
await config.afterAll()
|
||||
})
|
||||
|
||||
describe("POST /api/accounts/validate/email", () => {
|
||||
it("Returns 200", async () => {
|
||||
const email = generator.email()
|
||||
const res = await config.api.accounts.validateEmail(email)
|
||||
expect(res.status).toBe(200)
|
||||
})
|
||||
|
||||
it("returns 400", async () => {
|
||||
const [response, account] = await config.api.accounts.create({
|
||||
...fixtures.accounts.generateAccount()
|
||||
})
|
||||
const res = await config.api.accounts.validateEmail(account.email)
|
||||
expect(res.status).toBe(400)
|
||||
})
|
||||
})
|
||||
|
||||
describe("POST /api/accounts/validate/tenantId", () => {
|
||||
it("Returns 200", async () => {
|
||||
const res = await config.api.accounts.validateTenantId("randomtenant")
|
||||
expect(res.status).toBe(200)
|
||||
})
|
||||
|
||||
it("Returns 400", async () => {
|
||||
const [response, account] = await config.api.accounts.create({
|
||||
...fixtures.accounts.generateAccount()
|
||||
})
|
||||
const res = await config.api.accounts.validateTenantId(account.tenantId)
|
||||
expect(res.status).toBe(400)
|
||||
})
|
||||
})
|
||||
})
|
|
@ -1,56 +0,0 @@
|
|||
import TestConfiguration from "../../config/TestConfiguration"
|
||||
import * as fixtures from "../../fixtures"
|
||||
|
||||
describe("Account API - Verify Account", () => {
|
||||
const config = new TestConfiguration()
|
||||
|
||||
beforeAll(async () => {
|
||||
await config.beforeAll()
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
await config.afterAll()
|
||||
})
|
||||
|
||||
describe("POST /api/accounts/verify", () => {
|
||||
it("returns 200", async () => {
|
||||
// Create unverified account
|
||||
const createAccountRequest = fixtures.accounts.generateAccount()
|
||||
const [res, acc] = await config.api.accounts.create(
|
||||
createAccountRequest,
|
||||
{ doExpect: true, autoVerify: false })
|
||||
|
||||
// Attempt to log in using unverified account
|
||||
const [loginResponse, cookie] = await config.accountsApi.auth.login(
|
||||
createAccountRequest.email,
|
||||
createAccountRequest.password,
|
||||
)
|
||||
|
||||
// await config.login(
|
||||
// createAccountRequest.email,
|
||||
// createAccountRequest.password,
|
||||
// createAccountRequest.tenantId,
|
||||
// )
|
||||
|
||||
// Expect response - cannot login via unverified account
|
||||
|
||||
|
||||
// Verify account via code
|
||||
// await config.api.accounts.verifyAccount()
|
||||
|
||||
// Expect response - login successful
|
||||
})
|
||||
})
|
||||
|
||||
describe("POST /api/accounts/verify/send", () => {
|
||||
it("Send account verification email ", async () => {
|
||||
// Create account
|
||||
await config.api.accounts.create({
|
||||
...fixtures.accounts.generateAccount()
|
||||
})
|
||||
|
||||
// Verify account via email
|
||||
//await config.api.accounts.verifyAccountSendEmail()
|
||||
})
|
||||
})
|
||||
})
|
|
@ -10,8 +10,11 @@ const API_OPTS: APIRequestOpts = { doExpect: false }
|
|||
async function deleteAccount() {
|
||||
// @ts-ignore
|
||||
const accountID = global.qa.accountId
|
||||
// can't run 'expect' blocks in teardown
|
||||
await accountsApi.accounts.delete(accountID)
|
||||
|
||||
const [response] = await accountsApi.accounts.delete(accountID, { doExpect: false })
|
||||
if (response.status !== 204) {
|
||||
throw new Error(`status: ${response.status} not equal to expected: 201`)
|
||||
}
|
||||
}
|
||||
|
||||
async function teardown() {
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import { BudibaseInternalAPI } from "../internal-api"
|
||||
import { AccountInternalAPI } from "../account-api"
|
||||
import { CreateAppRequest, State } from "../types"
|
||||
import { APIRequestOpts, CreateAppRequest, State } from "../types"
|
||||
import * as fixtures from "../internal-api/fixtures"
|
||||
import { CreateAccountRequest } from "@budibase/types"
|
||||
|
||||
export default class BudibaseTestConfiguration {
|
||||
// apis
|
||||
|
@ -42,12 +43,12 @@ export default class BudibaseTestConfiguration {
|
|||
|
||||
// AUTH
|
||||
|
||||
async doInNewState(task: any) {
|
||||
async doInNewState(task: () => Promise<any>) {
|
||||
return this.doWithState(task, {})
|
||||
}
|
||||
|
||||
async doWithState(task: any, state: State) {
|
||||
const original = this.state
|
||||
async doWithState(task: () => Promise<any>, state: State) {
|
||||
const original = { ...this.state }
|
||||
|
||||
// override the state
|
||||
this.state.apiKey = state.apiKey
|
||||
|
@ -68,6 +69,15 @@ export default class BudibaseTestConfiguration {
|
|||
this.state.email = original.email
|
||||
}
|
||||
|
||||
async loginAsAccount(account: CreateAccountRequest, opts: APIRequestOpts = {}) {
|
||||
const [_, cookie] = await this.accountsApi.auth.login(
|
||||
account.email,
|
||||
account.password,
|
||||
opts
|
||||
)
|
||||
this.state.cookie = cookie
|
||||
}
|
||||
|
||||
async login(email: string, password: string, tenantId?: string) {
|
||||
if (!tenantId && this.state.tenantId) {
|
||||
tenantId = this.state.tenantId
|
||||
|
|
Loading…
Reference in New Issue