diff --git a/dictation_server/src/features/users/types/types.ts b/dictation_server/src/features/users/types/types.ts index 822a45b..2b5e8a4 100644 --- a/dictation_server/src/features/users/types/types.ts +++ b/dictation_server/src/features/users/types/types.ts @@ -331,6 +331,11 @@ export class MultipleImportUser { } export class PostMultipleImportsRequest { + @ApiProperty({ description: 'CSVファイル名' }) + @IsString() + @IsNotEmpty() + filename: string; + @ApiProperty({ type: [MultipleImportUser] }) @IsArray() @ValidateNested({ each: true }) @@ -345,10 +350,11 @@ export class MultipleImportErrors { @IsNotEmpty() name: string; - @ApiProperty({ description: 'メールアドレス' }) - @IsEmail({ blacklisted_chars: '*' }) + @ApiProperty({ description: 'エラー発生行数' }) + @IsInt() @IsNotEmpty() - email: string; + @Type(() => Number) + line: number; @ApiProperty({ description: 'エラーコード' }) @IsString() @@ -362,6 +368,17 @@ export class PostMultipleImportsCompleteRequest { @IsInt() accountId: number; + @ApiProperty({ description: 'CSVファイル名' }) + @IsString() + @IsNotEmpty() + filename: string; + + @ApiProperty({ description: '一括登録受付時刻(UNIXTIME/ミリ秒)' }) + @IsInt() + @IsNotEmpty() + @Type(() => Number) + requestTime: number; + @ApiProperty({ type: [MultipleImportErrors] }) @IsArray() @ValidateNested({ each: true }) diff --git a/dictation_server/src/features/users/users.controller.spec.ts b/dictation_server/src/features/users/users.controller.spec.ts index 2f93755..123c403 100644 --- a/dictation_server/src/features/users/users.controller.spec.ts +++ b/dictation_server/src/features/users/users.controller.spec.ts @@ -42,6 +42,7 @@ describe('UsersController', () => { describe('valdation PostMultipleImportsRequest', () => { it('role:noneの最低限の有効なリクエストが成功する', async () => { const request = new PostMultipleImportsRequest(); + request.filename = 'test.csv'; request.users = [ { name: 'namae', @@ -60,6 +61,7 @@ describe('UsersController', () => { it('role:authorの最低限の有効なリクエストが成功する', async () => { const request = new PostMultipleImportsRequest(); + request.filename = 'test.csv'; request.users = [ { name: 'namae', @@ -81,6 +83,7 @@ describe('UsersController', () => { it('emailがメールアドレスではない場合、バリデーションエラーが発生する', async () => { const request = new PostMultipleImportsRequest(); + request.filename = 'test.csv'; request.users = [ { name: 'namae', @@ -94,10 +97,11 @@ describe('UsersController', () => { const valdationObject = plainToClass(PostMultipleImportsRequest, request); const errors = await validate(valdationObject); - expect(errors.length).toBeGreaterThan(0); + expect(errors.length).toBe(1); }); it('AuthorなのにAuthorIDがない場合、バリデーションエラーが発生する', async () => { const request = new PostMultipleImportsRequest(); + request.filename = 'test.csv'; request.users = [ { name: 'namae', @@ -113,13 +117,14 @@ describe('UsersController', () => { const valdationObject = plainToClass(PostMultipleImportsRequest, request); const errors = await validate(valdationObject); - expect(errors.length).toBeGreaterThan(0); + expect(errors.length).toBe(1); }); it('AuthorIDがルールに違反していた場合、バリデーションエラーが発生する', async () => { // ルールに合致したAuthorIDではエラーが発生しない const validAuthorIDs = ['A', '_', 'AB', 'A1', '1A', '_1', 'A_B']; for await (const authorId of validAuthorIDs) { const request = new PostMultipleImportsRequest(); + request.filename = 'test.csv'; request.users = [ { name: 'namae', @@ -146,6 +151,7 @@ describe('UsersController', () => { const invalidAuthorIDs = ['a', '+', 'AB.', 'Ab', '1a', '_.', 'A/B', '']; for await (const authorId of invalidAuthorIDs) { const request = new PostMultipleImportsRequest(); + request.filename = 'test.csv'; request.users = [ { name: 'namae', @@ -165,11 +171,12 @@ describe('UsersController', () => { ); const errors = await validate(valdationObject); - expect(errors.length).toBeGreaterThan(0); + expect(errors.length).toBe(1); } }); it('Authorなのにencryptionがない場合、バリデーションエラーが発生する', async () => { const request = new PostMultipleImportsRequest(); + request.filename = 'test.csv'; request.users = [ { name: 'namae', @@ -185,10 +192,11 @@ describe('UsersController', () => { const valdationObject = plainToClass(PostMultipleImportsRequest, request); const errors = await validate(valdationObject); - expect(errors.length).toBeGreaterThan(0); + expect(errors.length).toBe(1); }); it('Authorなのにpromptがない場合、バリデーションエラーが発生する', async () => { const request = new PostMultipleImportsRequest(); + request.filename = 'test.csv'; request.users = [ { name: 'namae', @@ -204,10 +212,11 @@ describe('UsersController', () => { const valdationObject = plainToClass(PostMultipleImportsRequest, request); const errors = await validate(valdationObject); - expect(errors.length).toBeGreaterThan(0); + expect(errors.length).toBe(1); }); it('Authorでencryption:trueなのに、encryptionPasswordがない場合、バリデーションエラーが発生する', async () => { const request = new PostMultipleImportsRequest(); + request.filename = 'test.csv'; request.users = [ { name: 'namae', @@ -224,11 +233,12 @@ describe('UsersController', () => { const valdationObject = plainToClass(PostMultipleImportsRequest, request); const errors = await validate(valdationObject); - expect(errors.length).toBeGreaterThan(0); + expect(errors.length).toBe(1); }); it('Authorでencryption:trueでencryptionPasswordが正常であれば成功する', async () => { const request = new PostMultipleImportsRequest(); + request.filename = 'test.csv'; request.users = [ { name: 'namae', @@ -251,6 +261,7 @@ describe('UsersController', () => { it('encryptionPasswordが要件外(短い)の場合、バリデーションエラーが発生する', async () => { const request = new PostMultipleImportsRequest(); + request.filename = 'test.csv'; request.users = [ { name: 'namae', @@ -268,10 +279,11 @@ describe('UsersController', () => { const valdationObject = plainToClass(PostMultipleImportsRequest, request); const errors = await validate(valdationObject); - expect(errors.length).toBeGreaterThan(0); + expect(errors.length).toBe(1); }); it('encryptionPasswordが要件外(長い)の場合、バリデーションエラーが発生する', async () => { const request = new PostMultipleImportsRequest(); + request.filename = 'test.csv'; request.users = [ { name: 'namae', @@ -289,10 +301,11 @@ describe('UsersController', () => { const valdationObject = plainToClass(PostMultipleImportsRequest, request); const errors = await validate(valdationObject); - expect(errors.length).toBeGreaterThan(0); + expect(errors.length).toBe(1); }); it('encryptionPasswordが要件外(全角が含まれる)の場合、バリデーションエラーが発生する', async () => { const request = new PostMultipleImportsRequest(); + request.filename = 'test.csv'; request.users = [ { name: 'namae', @@ -310,11 +323,12 @@ describe('UsersController', () => { const valdationObject = plainToClass(PostMultipleImportsRequest, request); const errors = await validate(valdationObject); - expect(errors.length).toBeGreaterThan(0); + expect(errors.length).toBe(1); }); it('AuthorIDが要件外(小文字)の場合、バリデーションエラーが発生する', async () => { const request = new PostMultipleImportsRequest(); + request.filename = 'test.csv'; request.users = [ { name: 'namae', @@ -332,7 +346,7 @@ describe('UsersController', () => { const valdationObject = plainToClass(PostMultipleImportsRequest, request); const errors = await validate(valdationObject); - expect(errors.length).toBeGreaterThan(0); + expect(errors.length).toBe(1); }); }); @@ -340,6 +354,8 @@ describe('UsersController', () => { it('最低限の有効なリクエストが成功する', async () => { const request = new PostMultipleImportsCompleteRequest(); request.accountId = 1; + request.requestTime = new Date().getTime(); + request.filename = 'test.csv'; request.errors = []; const valdationObject = plainToClass( @@ -351,18 +367,36 @@ describe('UsersController', () => { expect(errors.length).toBe(0); }); + it('ファイル名が存在しなかった場合、バリデーションエラーが発生する', async () => { + const request = { + accountId: 1, + requestTime: new Date().getTime(), + errors: [], + }; + + const valdationObject = plainToClass( + PostMultipleImportsCompleteRequest, + request, + ); + + const errors = await validate(valdationObject); + expect(errors.length).toBe(1); + }); + it('エラーが存在するリクエストが成功する', async () => { const request = new PostMultipleImportsCompleteRequest(); request.accountId = 1; + request.requestTime = new Date().getTime(); + request.filename = 'test.csv'; request.errors = [ { name: 'namae', - email: 'hogehoge@example.com', + line: 1, errorCode: 'E1101', }, { name: 'namae', - email: 'hogehoge@example.com', + line: 1, errorCode: 'E1101', }, ]; @@ -379,14 +413,16 @@ describe('UsersController', () => { it('名前が足りないエラーがある場合、バリデーションエラーが発生する', async () => { const request = { accountId: 1, + filename: 'test.csv', + requestTime: new Date().getTime(), errors: [ { - email: 'hogehoge@example.com', + line: 1, errorCode: 'E1101', }, { name: 'namae', - email: 'hogehoge@example.com', + line: 1, errorCode: 'E1101', }, ], @@ -398,12 +434,14 @@ describe('UsersController', () => { ); const errors = await validate(valdationObject); - expect(errors.length).toBeGreaterThan(0); + expect(errors.length).toBe(1); }); - it('emailが足りないエラーがある場合、バリデーションエラーが発生する', async () => { + it('行指定が足りないエラーがある場合、バリデーションエラーが発生する', async () => { const request = { accountId: 1, + filename: 'test.csv', + requestTime: new Date().getTime(), errors: [ { name: 'namae', @@ -411,7 +449,7 @@ describe('UsersController', () => { }, { name: 'namae', - email: 'hogehoge@example.com', + line: 1, errorCode: 'E1101', }, ], @@ -423,20 +461,22 @@ describe('UsersController', () => { ); const errors = await validate(valdationObject); - expect(errors.length).toBeGreaterThan(0); + expect(errors.length).toBe(1); }); it('errorCodeが足りないエラーがある場合、バリデーションエラーが発生する', async () => { const request = { accountId: 1, + filename: 'test.csv', + requestTime: new Date().getTime(), errors: [ { name: 'namae', - email: 'hogehoge@example.com', + line: 1, }, { name: 'namae', - email: 'hogehoge@example.com', + line: 1, errorCode: 'E1101', }, ], @@ -448,21 +488,23 @@ describe('UsersController', () => { ); const errors = await validate(valdationObject); - expect(errors.length).toBeGreaterThan(0); + expect(errors.length).toBe(1); }); it('名前が空のエラーがある場合、バリデーションエラーが発生する', async () => { const request = { accountId: 1, + filename: 'test.csv', + requestTime: new Date().getTime(), errors: [ { name: '', - email: 'hogehoge@example.com', + line: 1, errorCode: 'E1101', }, { name: 'namae', - email: 'hogehoge@example.com', + line: 1, errorCode: 'E1101', }, ], @@ -474,20 +516,21 @@ describe('UsersController', () => { ); const errors = await validate(valdationObject); - expect(errors.length).toBeGreaterThan(0); + expect(errors.length).toBe(1); }); - it('emailが空のエラーがある場合、バリデーションエラーが発生する', async () => { + it('行数が空のエラーがある場合、バリデーションエラーが発生する', async () => { const request = { accountId: 1, + filename: 'test.csv', + requestTime: new Date().getTime(), errors: [ { name: 'namae', - email: '', errorCode: 'E1101', }, { name: 'namae', - email: 'hogehoge@example.com', + line: 1, errorCode: 'E1101', }, ], @@ -499,20 +542,22 @@ describe('UsersController', () => { ); const errors = await validate(valdationObject); - expect(errors.length).toBeGreaterThan(0); + expect(errors.length).toBe(1); }); - it('emailが空のエラーがある場合、バリデーションエラーが発生する', async () => { + it('エラーコードが空のエラーがある場合、バリデーションエラーが発生する', async () => { const request = { accountId: 1, + filename: 'test.csv', + requestTime: new Date().getTime(), errors: [ { name: 'namae', - email: 'hogehoge@example.com', + line: 1, errorCode: '', }, { name: 'namae', - email: 'hogehoge@example.com', + line: 1, errorCode: 'E1101', }, ], @@ -524,7 +569,7 @@ describe('UsersController', () => { ); const errors = await validate(valdationObject); - expect(errors.length).toBeGreaterThan(0); + expect(errors.length).toBe(1); }); }); });