fix: align admin profile request validation
This commit is contained in:
@@ -69,6 +69,22 @@ describe('AdminUsersController', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('admin user DTOs', () => {
|
describe('admin user DTOs', () => {
|
||||||
|
it('accepts omitted and string profile names but rejects explicit nulls', async () => {
|
||||||
|
const omitted = plainToInstance(AdminUserProfileDto, {});
|
||||||
|
const names = plainToInstance(AdminUserProfileDto, {
|
||||||
|
firstName: 'Ada',
|
||||||
|
lastName: 'Admin',
|
||||||
|
});
|
||||||
|
const nulls = plainToInstance(AdminUserProfileDto, {
|
||||||
|
firstName: null,
|
||||||
|
lastName: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(await validate(omitted)).toEqual([]);
|
||||||
|
expect(await validate(names)).toEqual([]);
|
||||||
|
expect(await validate(nulls)).not.toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
it('accepts only profile names in the profile DTO', async () => {
|
it('accepts only profile names in the profile DTO', async () => {
|
||||||
const dto = plainToInstance(AdminUserProfileDto, {
|
const dto = plainToInstance(AdminUserProfileDto, {
|
||||||
firstName: 'Ada',
|
firstName: 'Ada',
|
||||||
|
|||||||
@@ -7,20 +7,21 @@ import {
|
|||||||
Max,
|
Max,
|
||||||
MaxLength,
|
MaxLength,
|
||||||
Min,
|
Min,
|
||||||
|
ValidateIf,
|
||||||
} from 'class-validator';
|
} from 'class-validator';
|
||||||
import { RoleEnum } from '../../roles/roles.enum';
|
import { RoleEnum } from '../../roles/roles.enum';
|
||||||
import { StatusEnum } from '../../statuses/statuses.enum';
|
import { StatusEnum } from '../../statuses/statuses.enum';
|
||||||
|
|
||||||
export class AdminUserProfileDto {
|
export class AdminUserProfileDto {
|
||||||
@IsOptional()
|
@ValidateIf((_, value) => value !== undefined)
|
||||||
@IsString()
|
@IsString()
|
||||||
@MaxLength(255)
|
@MaxLength(255)
|
||||||
firstName?: string | null;
|
firstName?: string;
|
||||||
|
|
||||||
@IsOptional()
|
@ValidateIf((_, value) => value !== undefined)
|
||||||
@IsString()
|
@IsString()
|
||||||
@MaxLength(255)
|
@MaxLength(255)
|
||||||
lastName?: string | null;
|
lastName?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AdminUserRoleDto {
|
export class AdminUserRoleDto {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { TestBed } from '@angular/core/testing';
|
|||||||
import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing';
|
import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing';
|
||||||
import { environment } from '../../../environments/environment';
|
import { environment } from '../../../environments/environment';
|
||||||
import { AdminUsersApi } from './admin-users-api';
|
import { AdminUsersApi } from './admin-users-api';
|
||||||
|
import { AdminUserProfileRequest } from '../../models/user-directory.model';
|
||||||
import { UsersApi } from './users-api';
|
import { UsersApi } from './users-api';
|
||||||
|
|
||||||
describe('UsersApi', () => {
|
describe('UsersApi', () => {
|
||||||
@@ -32,6 +33,21 @@ describe('AdminUsersApi', () => {
|
|||||||
let service: AdminUsersApi;
|
let service: AdminUsersApi;
|
||||||
let httpMock: HttpTestingController;
|
let httpMock: HttpTestingController;
|
||||||
|
|
||||||
|
it('accepts profile requests with omitted or string names only', () => {
|
||||||
|
const omitted: AdminUserProfileRequest = {};
|
||||||
|
const names: AdminUserProfileRequest = {
|
||||||
|
firstName: 'Ada',
|
||||||
|
lastName: 'Admin',
|
||||||
|
};
|
||||||
|
|
||||||
|
// @ts-expect-error Profile names cannot be explicitly cleared to null.
|
||||||
|
const nullName: AdminUserProfileRequest = { firstName: null };
|
||||||
|
|
||||||
|
expect(omitted).toEqual({});
|
||||||
|
expect(names).toEqual({ firstName: 'Ada', lastName: 'Admin' });
|
||||||
|
expect(nullName).toEqual({ firstName: null });
|
||||||
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({ providers: [provideHttpClient(), provideHttpClientTesting()] });
|
TestBed.configureTestingModule({ providers: [provideHttpClient(), provideHttpClientTesting()] });
|
||||||
service = TestBed.inject(AdminUsersApi);
|
service = TestBed.inject(AdminUsersApi);
|
||||||
@@ -41,10 +57,10 @@ describe('AdminUsersApi', () => {
|
|||||||
afterEach(() => httpMock.verify());
|
afterEach(() => httpMock.verify());
|
||||||
|
|
||||||
it('uses the dedicated admin profile endpoint and payload', () => {
|
it('uses the dedicated admin profile endpoint and payload', () => {
|
||||||
service.updateProfile(7, { firstName: 'Alex', lastName: null }).subscribe();
|
service.updateProfile(7, { firstName: 'Alex' }).subscribe();
|
||||||
const request = httpMock.expectOne(`${environment.apiUrl}admin/users/7/profile`);
|
const request = httpMock.expectOne(`${environment.apiUrl}admin/users/7/profile`);
|
||||||
expect(request.request.method).toBe('PATCH');
|
expect(request.request.method).toBe('PATCH');
|
||||||
expect(request.request.body).toEqual({ firstName: 'Alex', lastName: null });
|
expect(request.request.body).toEqual({ firstName: 'Alex' });
|
||||||
request.flush({});
|
request.flush({});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -48,8 +48,8 @@ export interface UserDirectoryFilters {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface AdminUserProfileRequest {
|
export interface AdminUserProfileRequest {
|
||||||
firstName?: string | null;
|
firstName?: string;
|
||||||
lastName?: string | null;
|
lastName?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type AdminUserRoleId = 1 | 2;
|
export type AdminUserRoleId = 1 | 2;
|
||||||
|
|||||||
Reference in New Issue
Block a user