Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integration test for secret ops #1408

Merged
merged 20 commits into from
Feb 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
f09c48d
feat(e2e): fixed seed file issue and added more seeding
akhilmhdh Feb 15, 2024
00876f7
feat(e2e): added secrets integration tests
akhilmhdh Feb 15, 2024
90f09c7
feat(e2e): added service token integration tests
akhilmhdh Feb 15, 2024
4c49119
feat(e2e): added identity token secret access integration tests
akhilmhdh Feb 15, 2024
b24d748
feat(e2e): added gh action for execution of integration tests on PR a…
akhilmhdh Feb 15, 2024
793440f
feat(e2e): made rebased changes
akhilmhdh Feb 15, 2024
c71af00
feat(e2e): added enc key on gh action for be test file
akhilmhdh Feb 15, 2024
4f3cf04
feat(e2e): fixed post clean up error on gh be integration action
akhilmhdh Feb 15, 2024
b84579b
feat(e2e): changed to root .env.test and added .env.test.example
akhilmhdh Feb 15, 2024
c6c64b5
trigger workflow
maidul98 Feb 17, 2024
abd28d9
remove comment
maidul98 Feb 17, 2024
8864c81
feat: updated to reuse and run integration api test before release
akhilmhdh Feb 18, 2024
678306b
feat: some name changes for better understanding on testing
akhilmhdh Feb 18, 2024
7070a69
feat: made e2ee api test indepdent or stateless
akhilmhdh Feb 19, 2024
35d589a
add more secret test cases
maidul98 Feb 19, 2024
e4b8937
add env slug to make expect more strict
maidul98 Feb 19, 2024
d428fd0
update test envs
maidul98 Feb 19, 2024
2996efe
feat: made secrets ops test to have both identity and jwt token based…
akhilmhdh Feb 20, 2024
b4db06c
return empty string for decrypt fuction
maidul98 Feb 20, 2024
ccaa9fd
add more test cases
maidul98 Feb 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .env.test.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
REDIS_URL=redis://localhost:6379
DB_CONNECTION_URI=postgres://infisical:infisical@localhost/infisical?sslmode=disable
AUTH_SECRET=4bnfe4e407b8921c104518903515b218
ENCRYPTION_KEY=4bnfe4e407b8921c104518903515b218
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,17 @@ on:
- "infisical/v*.*.*-postgres"

jobs:
infisical-tests:
name: Run tests before deployment
runs-on: ubuntu-latest
steps:
- name: Run backend api integration tests
# https://docs.github.com/en/actions/using-workflows/reusing-workflows#overview
uses: ./.github/workflows/run-backend-tests.yml
maidul98 marked this conversation as resolved.
Show resolved Hide resolved
infisical-standalone:
name: Build infisical standalone image postgres
runs-on: ubuntu-latest
needs: [infisical-tests]
steps:
- name: Extract version from tag
id: extract_version
Expand Down
47 changes: 47 additions & 0 deletions .github/workflows/run-backend-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: "Run backend tests"

on:
pull_request:
types: [opened, synchronize]
paths:
- "backend/**"
- "!backend/README.md"
- "!backend/.*"
- "backend/.eslintrc.js"
workflow_call:

jobs:
check-be-pr:
name: Run integration test
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: ☁️ Checkout source
uses: actions/checkout@v3
- uses: KengoTODA/actions-setup-docker-compose@v1
if: ${{ env.ACT }}
maidul98 marked this conversation as resolved.
Show resolved Hide resolved
name: Install `docker-compose` for local simulations
with:
version: "2.14.2"
- name: 🔧 Setup Node 20
uses: actions/setup-node@v3
with:
node-version: "20"
cache: "npm"
cache-dependency-path: backend/package-lock.json
- name: Install dependencies
run: npm install
working-directory: backend
- name: Start postgres and redis
run: touch .env && docker-compose -f docker-compose.dev.yml up -d db redis
maidul98 marked this conversation as resolved.
Show resolved Hide resolved
- name: Start integration test
run: npm run test:e2e
working-directory: backend
env:
REDIS_URL: redis://172.17.0.1:6379
DB_CONNECTION_URI: postgres://infisical:[email protected]:5432/infisical?sslmode=disable
AUTH_SECRET: something-random
ENCRYPTION_KEY: 4bnfe4e407b8921c104518903515b218
- name: cleanup
run: |
docker-compose -f "docker-compose.dev.yml" down
akhilmhdh marked this conversation as resolved.
Show resolved Hide resolved
1 change: 1 addition & 0 deletions backend/.eslintignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
vitest-environment-infisical.ts
vitest.config.ts
vitest.e2e.config.ts
12 changes: 12 additions & 0 deletions backend/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,18 @@ module.exports = {
tsconfigRootDir: __dirname
},
root: true,
overrides: [
{
files: ["./e2e-test/**/*"],
rules: {
"@typescript-eslint/no-unsafe-member-access": "off",
"@typescript-eslint/no-unsafe-assignment": "off",
"@typescript-eslint/no-unsafe-argument": "off",
"@typescript-eslint/no-unsafe-return": "off",
"@typescript-eslint/no-unsafe-call": "off",
}
}
],
rules: {
"@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/no-unsafe-enum-comparison": "off",
Expand Down
71 changes: 71 additions & 0 deletions backend/e2e-test/routes/v1/identity.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { OrgMembershipRole } from "@app/db/schemas";
import { seedData1 } from "@app/db/seed-data";

export const createIdentity = async (name: string, role: string) => {
const createIdentityRes = await testServer.inject({
method: "POST",
url: "/api/v1/identities",
body: {
name,
role,
organizationId: seedData1.organization.id
},
headers: {
authorization: `Bearer ${jwtAuthToken}`
}
});
expect(createIdentityRes.statusCode).toBe(200);
return createIdentityRes.json().identity;
};

export const deleteIdentity = async (id: string) => {
const deleteIdentityRes = await testServer.inject({
method: "DELETE",
url: `/api/v1/identities/${id}`,
headers: {
authorization: `Bearer ${jwtAuthToken}`
}
});
expect(deleteIdentityRes.statusCode).toBe(200);
return deleteIdentityRes.json().identity;
};

describe("Identity v1", async () => {
test("Create identity", async () => {
const newIdentity = await createIdentity("mac1", OrgMembershipRole.Admin);
expect(newIdentity.name).toBe("mac1");
expect(newIdentity.authMethod).toBeNull();

await deleteIdentity(newIdentity.id);
});

test("Update identity", async () => {
const newIdentity = await createIdentity("mac1", OrgMembershipRole.Admin);
expect(newIdentity.name).toBe("mac1");
expect(newIdentity.authMethod).toBeNull();

const updatedIdentity = await testServer.inject({
method: "PATCH",
url: `/api/v1/identities/${newIdentity.id}`,
headers: {
authorization: `Bearer ${jwtAuthToken}`
},
body: {
name: "updated-mac-1",
role: OrgMembershipRole.Member
}
});

expect(updatedIdentity.statusCode).toBe(200);
expect(updatedIdentity.json().identity.name).toBe("updated-mac-1");

await deleteIdentity(newIdentity.id);
});

test("Delete Identity", async () => {
const newIdentity = await createIdentity("mac1", OrgMembershipRole.Admin);

const deletedIdentity = await deleteIdentity(newIdentity.id);
expect(deletedIdentity.name).toBe("mac1");
});
});
3 changes: 2 additions & 1 deletion backend/e2e-test/routes/v1/login.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { seedData1 } from "@app/db/seed-data";
import jsrp from "jsrp";

import { seedData1 } from "@app/db/seed-data";

describe("Login V1 Router", async () => {
// eslint-disable-next-line
maidul98 marked this conversation as resolved.
Show resolved Hide resolved
const client = new jsrp.client();
Expand Down
113 changes: 47 additions & 66 deletions backend/e2e-test/routes/v1/project-env.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,40 @@
import { seedData1 } from "@app/db/seed-data";
import { DEFAULT_PROJECT_ENVS } from "@app/db/seeds/3-project";

const createProjectEnvironment = async (name: string, slug: string) => {
const res = await testServer.inject({
method: "POST",
url: `/api/v1/workspace/${seedData1.project.id}/environments`,
headers: {
authorization: `Bearer ${jwtAuthToken}`
},
body: {
name,
slug
}
});

expect(res.statusCode).toBe(200);
const payload = JSON.parse(res.payload);
expect(payload).toHaveProperty("environment");
return payload.environment;
};

const deleteProjectEnvironment = async (envId: string) => {
const res = await testServer.inject({
method: "DELETE",
url: `/api/v1/workspace/${seedData1.project.id}/environments/${envId}`,
headers: {
authorization: `Bearer ${jwtAuthToken}`
}
});

expect(res.statusCode).toBe(200);
const payload = JSON.parse(res.payload);
expect(payload).toHaveProperty("environment");
return payload.environment;
};

describe("Project Environment Router", async () => {
test("Get default environments", async () => {
const res = await testServer.inject({
Expand Down Expand Up @@ -31,24 +65,10 @@ describe("Project Environment Router", async () => {
expect(payload.workspace.environments.length).toBe(3);
});

const mockProjectEnv = { name: "temp", slug: "temp", id: "" }; // id will be filled in create op
const mockProjectEnv = { name: "temp", slug: "temp" }; // id will be filled in create op
test("Create environment", async () => {
const res = await testServer.inject({
method: "POST",
url: `/api/v1/workspace/${seedData1.project.id}/environments`,
headers: {
authorization: `Bearer ${jwtAuthToken}`
},
body: {
name: mockProjectEnv.name,
slug: mockProjectEnv.slug
}
});

expect(res.statusCode).toBe(200);
const payload = JSON.parse(res.payload);
expect(payload).toHaveProperty("environment");
expect(payload.environment).toEqual(
const newEnvironment = await createProjectEnvironment(mockProjectEnv.name, mockProjectEnv.slug);
expect(newEnvironment).toEqual(
expect.objectContaining({
id: expect.any(String),
name: mockProjectEnv.name,
Expand All @@ -59,14 +79,15 @@ describe("Project Environment Router", async () => {
updatedAt: expect.any(String)
})
);
mockProjectEnv.id = payload.environment.id;
await deleteProjectEnvironment(newEnvironment.id);
});

test("Update environment", async () => {
const newEnvironment = await createProjectEnvironment(mockProjectEnv.name, mockProjectEnv.slug);
const updatedName = { name: "temp#2", slug: "temp2" };
const res = await testServer.inject({
method: "PATCH",
url: `/api/v1/workspace/${seedData1.project.id}/environments/${mockProjectEnv.id}`,
url: `/api/v1/workspace/${seedData1.project.id}/environments/${newEnvironment.id}`,
headers: {
authorization: `Bearer ${jwtAuthToken}`
},
Expand All @@ -82,7 +103,7 @@ describe("Project Environment Router", async () => {
expect(payload).toHaveProperty("environment");
expect(payload.environment).toEqual(
expect.objectContaining({
id: expect.any(String),
id: newEnvironment.id,
name: updatedName.name,
slug: updatedName.slug,
projectId: seedData1.project.id,
Expand All @@ -91,61 +112,21 @@ describe("Project Environment Router", async () => {
updatedAt: expect.any(String)
})
);
mockProjectEnv.name = updatedName.name;
mockProjectEnv.slug = updatedName.slug;
await deleteProjectEnvironment(newEnvironment.id);
});

test("Delete environment", async () => {
const res = await testServer.inject({
method: "DELETE",
url: `/api/v1/workspace/${seedData1.project.id}/environments/${mockProjectEnv.id}`,
headers: {
authorization: `Bearer ${jwtAuthToken}`
}
});

expect(res.statusCode).toBe(200);
const payload = JSON.parse(res.payload);
expect(payload).toHaveProperty("environment");
expect(payload.environment).toEqual(
const newEnvironment = await createProjectEnvironment(mockProjectEnv.name, mockProjectEnv.slug);
const deletedProjectEnvironment = await deleteProjectEnvironment(newEnvironment.id);
expect(deletedProjectEnvironment).toEqual(
expect.objectContaining({
id: expect.any(String),
id: deletedProjectEnvironment.id,
name: mockProjectEnv.name,
slug: mockProjectEnv.slug,
position: 1,
position: 4,
createdAt: expect.any(String),
updatedAt: expect.any(String)
})
);
});

// after all these opreations the list of environment should be still same
test("Default list of environment", async () => {
const res = await testServer.inject({
method: "GET",
url: `/api/v1/workspace/${seedData1.project.id}`,
headers: {
authorization: `Bearer ${jwtAuthToken}`
}
});

expect(res.statusCode).toBe(200);
const payload = JSON.parse(res.payload);
expect(payload).toHaveProperty("workspace");
// check for default environments
expect(payload).toEqual({
workspace: expect.objectContaining({
name: seedData1.project.name,
id: seedData1.project.id,
slug: seedData1.project.slug,
environments: expect.arrayContaining([
expect.objectContaining(DEFAULT_PROJECT_ENVS[0]),
expect.objectContaining(DEFAULT_PROJECT_ENVS[1]),
expect.objectContaining(DEFAULT_PROJECT_ENVS[2])
])
})
});
// ensure only two default environments exist
expect(payload.workspace.environments.length).toBe(3);
});
});
Loading
Loading