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

feat: implement control-plane service and testing #1

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { AuthDetails, Permissions } from "../../app/shemas";
import { ForAuthenticating } from "../../ports/drivens";

const authDetailsMock: AuthDetails = {
token: "it's a token",
refreshToken: "it's a cool token",
};

interface userMock extends Permissions {
email: string;
password: string;
}

const users: userMock[] = [
{
user: true,
admin: true,
email: "[email protected]",
password: "It's John Cena",
},
{
user: true,
admin: false,
email: "[email protected]",
password: "123456",
},
];

export class ControlAuthenticatorStub implements ForAuthenticating {
async getAuthDetails(email: string, password: string): Promise<AuthDetails> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Esto está muy bien, si quieres puedes poner que siempre devuelva un mock sin necesidad de agregar lógica de búsqueda ya que justamente es eso, es para controlar la lógica principal en un ambiente controlado

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

La lógica en sí deberías de hacerla en el control plane ya que es parte del domain

const user = users.find(
(curUser) => curUser.email == email && curUser.password == password
);

if (!user) {
throw new Error("user does not authenticated");
}

return Promise.resolve(authDetailsMock);
}

async getPermissions(email: string, password: string): Promise<Permissions> {
const user = users.find(
(curUser) => curUser.email == email && curUser.password == password
);

if (!user) {
throw new Error("user does not have permissions");
}

return Promise.resolve({ admin: user.admin, user: user.user });
}
}
1 change: 1 addition & 0 deletions src/services/control-plane/adapters/drivens/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./for-authenticador-stub-adapter";
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { ControlPlane } from "../../app/control-plane";
import { AuthDetails, Permissions } from "../../app/shemas";
import { ForAuthenticatingUser } from "../../ports/drivers";

export class ControlAuthenticatingProxyAdapter
implements ForAuthenticatingUser
{
constructor(private readonly controlPlane: ControlPlane) {}

async getAuthDetails(email: string, password: string): Promise<AuthDetails> {
return this.controlPlane.getAuthDetails(email, password);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agregar espacio entre métodos y secciones lógicas

Suggested change
}
}

async getPermissions(email: string, password: string): Promise<Permissions> {
return this.controlPlane.getPermissions(email, password);
}
}
1 change: 1 addition & 0 deletions src/services/control-plane/adapters/drivers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./control-authenticating-proxy";
16 changes: 16 additions & 0 deletions src/services/control-plane/app/composition-root.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { ControlPlane } from "./control-plane";
import { ControlAuthenticatorStub } from "../adapters/drivens";
import { ControlAuthenticatingProxyAdapter } from "../adapters/drivers";

export const compositionMock = () => {
const authenticatorStub = new ControlAuthenticatorStub();
const controlPlane = new ControlPlane(authenticatorStub);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

llamarlo controlPlaneMock, ya que justamente es un mock del control plane

const controlAuthenticatingProxyAdapter =
new ControlAuthenticatingProxyAdapter(controlPlane);

return {
controlAuthenticatingProxyAdapter,
};
};

export const { controlAuthenticatingProxyAdapter } = compositionMock();
90 changes: 90 additions & 0 deletions src/services/control-plane/app/control-plane.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { describe, expect, it } from "vitest";
import { ControlPlane } from "./control-plane";
import { ControlAuthenticatorStub } from "../adapters/drivens";
import { ControlAuthenticatingProxyAdapter } from "../adapters/drivers";
import { AuthDetails, Permissions } from "./shemas";

describe("Control Plane", () => {
const authenticatorStub = new ControlAuthenticatorStub();
const controlPlane = new ControlPlane(authenticatorStub);
const controlAuthenticatingProxyAdapter =
new ControlAuthenticatingProxyAdapter(controlPlane);

it.concurrent("should return a token an refreshToken", async () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

faltan los
//GIVEN
//WHEN
//THEN

const mockedUser = {
email: "[email protected]",
password: "It's John Cena",
};

const expectResult: AuthDetails = {
token: "it's a token",
refreshToken: "it's a cool token",
};

const result = await controlAuthenticatingProxyAdapter.getAuthDetails(
mockedUser.email,
mockedUser.password
);

expect(result).toEqual(expectResult);
});

it.concurrent("should throw error ", async () => {
const mockedUser = {
email: "[email protected]",
password: "Simon si soy",
};

const expectResult: AuthDetails = {
token: "it's a token",
refreshToken: "it's a cool token",
};
let result;

try {
result = await controlAuthenticatingProxyAdapter.getAuthDetails(
mockedUser.email,
mockedUser.password
);
} catch (e) {}
expect(result).not.toEqual(expectResult);
});

it.concurrent("should be return user permission only", async () => {
const mockedUser = {
email: "[email protected]",
password: "123456",
};

const expectResult: Permissions = {
admin: false,
user: true,
};

const result = await controlAuthenticatingProxyAdapter.getPermissions(
mockedUser.email,
mockedUser.password
);

expect(result).toEqual(expectResult);
});

it.concurrent("should be return both permissions", async () => {
const mockedUser = {
email: "[email protected]",
password: "It's John Cena",
};

const expectResult: Permissions = {
admin: true,
user: true,
};

const result = await controlAuthenticatingProxyAdapter.getPermissions(
mockedUser.email,
mockedUser.password
);

expect(result).toEqual(expectResult);
});
});
14 changes: 14 additions & 0 deletions src/services/control-plane/app/control-plane.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { ForAuthenticatingUser } from "../ports/drivers";
import { AuthDetails, Permissions } from "./shemas";
import { ForAuthenticating } from "../ports/drivens";

export class ControlPlane implements ForAuthenticatingUser {
constructor(private readonly handlerAuthorization: ForAuthenticating) {}

async getAuthDetails(email: string, password: string): Promise<AuthDetails> {
return this.handlerAuthorization.getAuthDetails(email, password);
}
async getPermissions(email: string, password: string): Promise<Permissions> {
return this.handlerAuthorization.getPermissions(email, password);
}
}
4 changes: 4 additions & 0 deletions src/services/control-plane/app/shemas/authDetails.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface AuthDetails {
token: string;
refreshToken: string;
}
2 changes: 2 additions & 0 deletions src/services/control-plane/app/shemas/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./authDetails";
export * from "./permissions";
4 changes: 4 additions & 0 deletions src/services/control-plane/app/shemas/permissions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface Permissions {
admin: boolean;
user: boolean;
}
6 changes: 6 additions & 0 deletions src/services/control-plane/ports/drivens/for-auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { AuthDetails, Permissions } from "../../app/shemas";

export interface ForAuthenticating {
getAuthDetails(email: string, password: string): Promise<AuthDetails>;
getPermissions(email: string, password: string): Promise<Permissions>;
}
1 change: 1 addition & 0 deletions src/services/control-plane/ports/drivens/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./for-auth";
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { AuthDetails, Permissions } from "../../app/shemas";

export interface ForAuthenticatingUser {
getAuthDetails(email: string, password: string): Promise<AuthDetails>;
getPermissions(email: string, password: string): Promise<Permissions>;
}
1 change: 1 addition & 0 deletions src/services/control-plane/ports/drivers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./for-authenticating-user";