Skip to content

Commit

Permalink
incorporated LoadAvatarConfigUseCase into UpdateAvatarConfigUseCase
Browse files Browse the repository at this point in the history
  • Loading branch information
DerKatsche committed Dec 10, 2024
1 parent bf847dd commit 58f92b7
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 35 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ISynchronousUsecase } from "../../Abstract/ISynchronousUsecase";
import { IAsyncUsecase } from "../../Abstract/IAsyncUsecase";
import AvatarConfigTO from "../../DataTransferObjects/AvatarConfigTO";

export default interface IUpdateAvatarConfigUseCase
extends ISynchronousUsecase<Partial<AvatarConfigTO>, void> {}
extends IAsyncUsecase<Partial<AvatarConfigTO>, void> {}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import type IEntityContainer from "../../../Domain/EntityContainer/IEntityContai
import AvatarConfigTO from "../../DataTransferObjects/AvatarConfigTO";
import PORT_TYPES from "~DependencyInjection/Ports/PORT_TYPES";
import type IAvatarPort from "../../Ports/Interfaces/IAvatarPort";
import AvatarEntity from "src/Components/Core/Domain/Entities/AvatarEntity";
import UserDataEntity from "src/Components/Core/Domain/Entities/UserDataEntity";
import type ILoggerPort from "../../Ports/Interfaces/ILoggerPort";
import { LogLevelTypes } from "src/Components/Core/Domain/Types/LogLevelTypes";
import USECASE_TYPES from "~DependencyInjection/UseCases/USECASE_TYPES";
import type ILoadAvatarConfigUseCase from "../LoadAvatarConfig/ILoadAvatarConfigUseCase";

@injectable()
export default class UpdateAvatarConfigUseCase
Expand All @@ -21,9 +22,11 @@ export default class UpdateAvatarConfigUseCase
private avatarPort: IAvatarPort,
@inject(CORE_TYPES.ILogger)
private logger: ILoggerPort,
@inject(USECASE_TYPES.ILoadAvatarConfigUseCase)
private loadAvatarUseCase: ILoadAvatarConfigUseCase,
) {}

execute(newAvatarConfig: Partial<AvatarConfigTO>): void {
async executeAsync(newAvatarConfig: Partial<AvatarConfigTO>): Promise<void> {
let userDataEntities =
this.entityContainer.getEntitiesOfType(UserDataEntity);
if (userDataEntities.length === 0) {
Expand All @@ -34,17 +37,9 @@ export default class UpdateAvatarConfigUseCase
return;
}

// TODO: this is a workaround when no config is available, remove when loading initial avatar config is implemented
if (!userDataEntities[0].avatar) {
userDataEntities[0].avatar = Object.assign(
new AvatarEntity(),
newAvatarConfig,
);
this.avatarPort.onAvatarConfigChanged(
Object.assign({}, userDataEntities[0].avatar), // clone to prevent changes to propagate
newAvatarConfig,
);
}
// load avatar config if not already loaded
if (!userDataEntities[0].avatar)
await this.loadAvatarUseCase.executeAsync();

// compute difference between new and current avatar config
let difference: any = {}; // actually Partial<AvatarConfigTO>, but TS doesn't like that
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const USECASE_TYPES = {
"ISetWorldCompletionModalToShownUseCase",
),
ILoadLearningWorldUseCase: Symbol("ILoadLearningWorldUseCase"),
ILoadAvatarUseCase: Symbol("ILoadAvatarUseCase"),
ILoadAvatarConfigUseCase: Symbol("ILoadAvatarConfigUseCase"),
ILoadLearningElementUseCase: Symbol("ILoadLearningElementUseCase"),
IScoreLearningElementUseCase: Symbol("IScoreLearningElementUseCase"),
ICalculateLearningSpaceScoreUseCase: Symbol(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ const UseCaseDIContainer = new ContainerModule((bind) => {
.to(SetWorldCompletionModalToShownUseCase)
.inSingletonScope();

bind<ILoadAvatarConfigUseCase>(USECASE_TYPES.ILoadAvatarUseCase)
bind<ILoadAvatarConfigUseCase>(USECASE_TYPES.ILoadAvatarConfigUseCase)
.to(LoadAvatarConfigUseCase)
.inSingletonScope();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,8 @@ import USECASE_TYPES from "~DependencyInjection/UseCases/USECASE_TYPES";

export default class AvatarEditorController implements IAvatarEditorController {
onAvatarConfigChanged(changes: Partial<AvatarConfigTO>): void {
const updateAvatarConfigUseCase =
CoreDIContainer.get<IUpdateAvatarConfigUseCase>(
USECASE_TYPES.IUpdateAvatarConfigUseCase,
);

updateAvatarConfigUseCase.execute(changes);
CoreDIContainer.get<IUpdateAvatarConfigUseCase>(
USECASE_TYPES.IUpdateAvatarConfigUseCase,
).executeAsync(changes);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,29 +39,39 @@ describe("UpdateAvatarConfigUseCase", () => {
CoreDIContainer.restore();
});

test("logs error if no user data entity found", () => {
test("logs error if no user data entity found", async () => {
entityContainerMock.getEntitiesOfType.mockReturnValue([]);

systemUnderTest.execute({});
await systemUnderTest.executeAsync({});

expect(loggerMock.log).toHaveBeenCalledWith(
LogLevelTypes.ERROR,
"No user data entity found",
);
});

test("logs error if multiple user data entities found", () => {
test("logs error if multiple user data entities found", async () => {
entityContainerMock.getEntitiesOfType.mockReturnValue([{}, {}]);

systemUnderTest.execute({});
await systemUnderTest.executeAsync({});

expect(loggerMock.log).toHaveBeenCalledWith(
LogLevelTypes.ERROR,
"Multiple user data entities found",
);
});

test("updates avatar config in user data entity", () => {
test("calls loadAvatarConfigUseCase if avatar config not loaded", async () => {
const userDataEntity = {};

entityContainerMock.getEntitiesOfType.mockReturnValue([userDataEntity]);

await systemUnderTest.executeAsync({});

expect(avatarPortMock.onAvatarConfigLoaded).toHaveBeenCalledTimes(1);
});

test("updates avatar config in user data entity", async () => {
const avatarConfig: Partial<AvatarConfigTO> = {
roundness: 0.5,
};
Expand All @@ -74,15 +84,15 @@ describe("UpdateAvatarConfigUseCase", () => {

entityContainerMock.getEntitiesOfType.mockReturnValue([userDataEntity]);

systemUnderTest.execute(avatarConfig);
await systemUnderTest.executeAsync(avatarConfig);

expect(userDataEntity.avatar.roundness).toEqual(0.5);
expect(userDataEntity.avatar.hair).toEqual(
OAvatarHairModels.MediumPonytail,
);
});

test("calls onAvatarConfigChanged on avatar port", () => {
test("calls onAvatarConfigChanged on avatar port", async () => {
const avatarConfig: Partial<AvatarConfigTO> = {
roundness: 0.5,
};
Expand All @@ -95,15 +105,15 @@ describe("UpdateAvatarConfigUseCase", () => {

entityContainerMock.getEntitiesOfType.mockReturnValue([userDataEntity]);

systemUnderTest.execute(avatarConfig);
await systemUnderTest.executeAsync(avatarConfig);

expect(avatarPortMock.onAvatarConfigChanged).toHaveBeenCalledWith(
userDataEntity.avatar,
avatarConfig,
);
});

test("doesn't call onAvatarConfigChanged when change is already present in current config", () => {
test("doesn't call onAvatarConfigChanged when change is already present in current config", async () => {
const avatarConfig: Partial<AvatarConfigTO> = {
roundness: 0.5,
};
Expand All @@ -116,20 +126,20 @@ describe("UpdateAvatarConfigUseCase", () => {

entityContainerMock.getEntitiesOfType.mockReturnValue([userDataEntity]);

systemUnderTest.execute(avatarConfig);
await systemUnderTest.executeAsync(avatarConfig);

expect(avatarPortMock.onAvatarConfigChanged).not.toHaveBeenCalled();
});

test("diff and new avatar config passed to onAvatarConfigChanged do match", () => {
test("diff and new avatar config passed to onAvatarConfigChanged do match", async () => {
const avatarConfig: Partial<AvatarConfigTO> = {
roundness: 0.5,
};
const userDataEntity = {};

entityContainerMock.getEntitiesOfType.mockReturnValue([userDataEntity]);

systemUnderTest.execute(avatarConfig);
await systemUnderTest.executeAsync(avatarConfig);

expect(
avatarPortMock.onAvatarConfigChanged.mock.lastCall![0],
Expand Down

0 comments on commit 58f92b7

Please sign in to comment.