Merged PR 787: API I/F修正

## 概要
[Task3793: API I/F修正](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/3793)

- OMDS様とのメール文面調整の結果、csvファイル名もAPIで受け渡す必要が出てきたためAPI I/Fを修正する
  - 一括登録依頼API、一括登録完了APIの両方に「ファイル名」を追加
- 増えたプロパティのバリデーションをするテストを追加

## レビューポイント
- プロパティ名は妥当か
- テストの内容は十分か

## 動作確認状況
- npm run testを通過
This commit is contained in:
湯本 開 2024-02-28 05:30:09 +00:00
parent dd8bddc971
commit 71127a6db9
2 changed files with 97 additions and 35 deletions

View File

@ -331,6 +331,11 @@ export class MultipleImportUser {
} }
export class PostMultipleImportsRequest { export class PostMultipleImportsRequest {
@ApiProperty({ description: 'CSVファイル名' })
@IsString()
@IsNotEmpty()
filename: string;
@ApiProperty({ type: [MultipleImportUser] }) @ApiProperty({ type: [MultipleImportUser] })
@IsArray() @IsArray()
@ValidateNested({ each: true }) @ValidateNested({ each: true })
@ -345,10 +350,11 @@ export class MultipleImportErrors {
@IsNotEmpty() @IsNotEmpty()
name: string; name: string;
@ApiProperty({ description: 'メールアドレス' }) @ApiProperty({ description: 'エラー発生行数' })
@IsEmail({ blacklisted_chars: '*' }) @IsInt()
@IsNotEmpty() @IsNotEmpty()
email: string; @Type(() => Number)
line: number;
@ApiProperty({ description: 'エラーコード' }) @ApiProperty({ description: 'エラーコード' })
@IsString() @IsString()
@ -362,6 +368,17 @@ export class PostMultipleImportsCompleteRequest {
@IsInt() @IsInt()
accountId: number; accountId: number;
@ApiProperty({ description: 'CSVファイル名' })
@IsString()
@IsNotEmpty()
filename: string;
@ApiProperty({ description: '一括登録受付時刻(UNIXTIME/ミリ秒)' })
@IsInt()
@IsNotEmpty()
@Type(() => Number)
requestTime: number;
@ApiProperty({ type: [MultipleImportErrors] }) @ApiProperty({ type: [MultipleImportErrors] })
@IsArray() @IsArray()
@ValidateNested({ each: true }) @ValidateNested({ each: true })

View File

@ -42,6 +42,7 @@ describe('UsersController', () => {
describe('valdation PostMultipleImportsRequest', () => { describe('valdation PostMultipleImportsRequest', () => {
it('role:noneの最低限の有効なリクエストが成功する', async () => { it('role:noneの最低限の有効なリクエストが成功する', async () => {
const request = new PostMultipleImportsRequest(); const request = new PostMultipleImportsRequest();
request.filename = 'test.csv';
request.users = [ request.users = [
{ {
name: 'namae', name: 'namae',
@ -60,6 +61,7 @@ describe('UsersController', () => {
it('role:authorの最低限の有効なリクエストが成功する', async () => { it('role:authorの最低限の有効なリクエストが成功する', async () => {
const request = new PostMultipleImportsRequest(); const request = new PostMultipleImportsRequest();
request.filename = 'test.csv';
request.users = [ request.users = [
{ {
name: 'namae', name: 'namae',
@ -81,6 +83,7 @@ describe('UsersController', () => {
it('emailがメールアドレスではない場合、バリデーションエラーが発生する', async () => { it('emailがメールアドレスではない場合、バリデーションエラーが発生する', async () => {
const request = new PostMultipleImportsRequest(); const request = new PostMultipleImportsRequest();
request.filename = 'test.csv';
request.users = [ request.users = [
{ {
name: 'namae', name: 'namae',
@ -94,10 +97,11 @@ describe('UsersController', () => {
const valdationObject = plainToClass(PostMultipleImportsRequest, request); const valdationObject = plainToClass(PostMultipleImportsRequest, request);
const errors = await validate(valdationObject); const errors = await validate(valdationObject);
expect(errors.length).toBeGreaterThan(0); expect(errors.length).toBe(1);
}); });
it('AuthorなのにAuthorIDがない場合、バリデーションエラーが発生する', async () => { it('AuthorなのにAuthorIDがない場合、バリデーションエラーが発生する', async () => {
const request = new PostMultipleImportsRequest(); const request = new PostMultipleImportsRequest();
request.filename = 'test.csv';
request.users = [ request.users = [
{ {
name: 'namae', name: 'namae',
@ -113,13 +117,14 @@ describe('UsersController', () => {
const valdationObject = plainToClass(PostMultipleImportsRequest, request); const valdationObject = plainToClass(PostMultipleImportsRequest, request);
const errors = await validate(valdationObject); const errors = await validate(valdationObject);
expect(errors.length).toBeGreaterThan(0); expect(errors.length).toBe(1);
}); });
it('AuthorIDがルールに違反していた場合、バリデーションエラーが発生する', async () => { it('AuthorIDがルールに違反していた場合、バリデーションエラーが発生する', async () => {
// ルールに合致したAuthorIDではエラーが発生しない // ルールに合致したAuthorIDではエラーが発生しない
const validAuthorIDs = ['A', '_', 'AB', 'A1', '1A', '_1', 'A_B']; const validAuthorIDs = ['A', '_', 'AB', 'A1', '1A', '_1', 'A_B'];
for await (const authorId of validAuthorIDs) { for await (const authorId of validAuthorIDs) {
const request = new PostMultipleImportsRequest(); const request = new PostMultipleImportsRequest();
request.filename = 'test.csv';
request.users = [ request.users = [
{ {
name: 'namae', name: 'namae',
@ -146,6 +151,7 @@ describe('UsersController', () => {
const invalidAuthorIDs = ['a', '+', 'AB.', 'Ab', '1a', '_.', 'A/B', '']; const invalidAuthorIDs = ['a', '+', 'AB.', 'Ab', '1a', '_.', 'A/B', ''];
for await (const authorId of invalidAuthorIDs) { for await (const authorId of invalidAuthorIDs) {
const request = new PostMultipleImportsRequest(); const request = new PostMultipleImportsRequest();
request.filename = 'test.csv';
request.users = [ request.users = [
{ {
name: 'namae', name: 'namae',
@ -165,11 +171,12 @@ describe('UsersController', () => {
); );
const errors = await validate(valdationObject); const errors = await validate(valdationObject);
expect(errors.length).toBeGreaterThan(0); expect(errors.length).toBe(1);
} }
}); });
it('Authorなのにencryptionがない場合、バリデーションエラーが発生する', async () => { it('Authorなのにencryptionがない場合、バリデーションエラーが発生する', async () => {
const request = new PostMultipleImportsRequest(); const request = new PostMultipleImportsRequest();
request.filename = 'test.csv';
request.users = [ request.users = [
{ {
name: 'namae', name: 'namae',
@ -185,10 +192,11 @@ describe('UsersController', () => {
const valdationObject = plainToClass(PostMultipleImportsRequest, request); const valdationObject = plainToClass(PostMultipleImportsRequest, request);
const errors = await validate(valdationObject); const errors = await validate(valdationObject);
expect(errors.length).toBeGreaterThan(0); expect(errors.length).toBe(1);
}); });
it('Authorなのにpromptがない場合、バリデーションエラーが発生する', async () => { it('Authorなのにpromptがない場合、バリデーションエラーが発生する', async () => {
const request = new PostMultipleImportsRequest(); const request = new PostMultipleImportsRequest();
request.filename = 'test.csv';
request.users = [ request.users = [
{ {
name: 'namae', name: 'namae',
@ -204,10 +212,11 @@ describe('UsersController', () => {
const valdationObject = plainToClass(PostMultipleImportsRequest, request); const valdationObject = plainToClass(PostMultipleImportsRequest, request);
const errors = await validate(valdationObject); const errors = await validate(valdationObject);
expect(errors.length).toBeGreaterThan(0); expect(errors.length).toBe(1);
}); });
it('Authorでencryption:trueなのに、encryptionPasswordがない場合、バリデーションエラーが発生する', async () => { it('Authorでencryption:trueなのに、encryptionPasswordがない場合、バリデーションエラーが発生する', async () => {
const request = new PostMultipleImportsRequest(); const request = new PostMultipleImportsRequest();
request.filename = 'test.csv';
request.users = [ request.users = [
{ {
name: 'namae', name: 'namae',
@ -224,11 +233,12 @@ describe('UsersController', () => {
const valdationObject = plainToClass(PostMultipleImportsRequest, request); const valdationObject = plainToClass(PostMultipleImportsRequest, request);
const errors = await validate(valdationObject); const errors = await validate(valdationObject);
expect(errors.length).toBeGreaterThan(0); expect(errors.length).toBe(1);
}); });
it('Authorでencryption:trueでencryptionPasswordが正常であれば成功する', async () => { it('Authorでencryption:trueでencryptionPasswordが正常であれば成功する', async () => {
const request = new PostMultipleImportsRequest(); const request = new PostMultipleImportsRequest();
request.filename = 'test.csv';
request.users = [ request.users = [
{ {
name: 'namae', name: 'namae',
@ -251,6 +261,7 @@ describe('UsersController', () => {
it('encryptionPasswordが要件外(短い)の場合、バリデーションエラーが発生する', async () => { it('encryptionPasswordが要件外(短い)の場合、バリデーションエラーが発生する', async () => {
const request = new PostMultipleImportsRequest(); const request = new PostMultipleImportsRequest();
request.filename = 'test.csv';
request.users = [ request.users = [
{ {
name: 'namae', name: 'namae',
@ -268,10 +279,11 @@ describe('UsersController', () => {
const valdationObject = plainToClass(PostMultipleImportsRequest, request); const valdationObject = plainToClass(PostMultipleImportsRequest, request);
const errors = await validate(valdationObject); const errors = await validate(valdationObject);
expect(errors.length).toBeGreaterThan(0); expect(errors.length).toBe(1);
}); });
it('encryptionPasswordが要件外(長い)の場合、バリデーションエラーが発生する', async () => { it('encryptionPasswordが要件外(長い)の場合、バリデーションエラーが発生する', async () => {
const request = new PostMultipleImportsRequest(); const request = new PostMultipleImportsRequest();
request.filename = 'test.csv';
request.users = [ request.users = [
{ {
name: 'namae', name: 'namae',
@ -289,10 +301,11 @@ describe('UsersController', () => {
const valdationObject = plainToClass(PostMultipleImportsRequest, request); const valdationObject = plainToClass(PostMultipleImportsRequest, request);
const errors = await validate(valdationObject); const errors = await validate(valdationObject);
expect(errors.length).toBeGreaterThan(0); expect(errors.length).toBe(1);
}); });
it('encryptionPasswordが要件外(全角が含まれる)の場合、バリデーションエラーが発生する', async () => { it('encryptionPasswordが要件外(全角が含まれる)の場合、バリデーションエラーが発生する', async () => {
const request = new PostMultipleImportsRequest(); const request = new PostMultipleImportsRequest();
request.filename = 'test.csv';
request.users = [ request.users = [
{ {
name: 'namae', name: 'namae',
@ -310,11 +323,12 @@ describe('UsersController', () => {
const valdationObject = plainToClass(PostMultipleImportsRequest, request); const valdationObject = plainToClass(PostMultipleImportsRequest, request);
const errors = await validate(valdationObject); const errors = await validate(valdationObject);
expect(errors.length).toBeGreaterThan(0); expect(errors.length).toBe(1);
}); });
it('AuthorIDが要件外(小文字)の場合、バリデーションエラーが発生する', async () => { it('AuthorIDが要件外(小文字)の場合、バリデーションエラーが発生する', async () => {
const request = new PostMultipleImportsRequest(); const request = new PostMultipleImportsRequest();
request.filename = 'test.csv';
request.users = [ request.users = [
{ {
name: 'namae', name: 'namae',
@ -332,7 +346,7 @@ describe('UsersController', () => {
const valdationObject = plainToClass(PostMultipleImportsRequest, request); const valdationObject = plainToClass(PostMultipleImportsRequest, request);
const errors = await validate(valdationObject); const errors = await validate(valdationObject);
expect(errors.length).toBeGreaterThan(0); expect(errors.length).toBe(1);
}); });
}); });
@ -340,6 +354,8 @@ describe('UsersController', () => {
it('最低限の有効なリクエストが成功する', async () => { it('最低限の有効なリクエストが成功する', async () => {
const request = new PostMultipleImportsCompleteRequest(); const request = new PostMultipleImportsCompleteRequest();
request.accountId = 1; request.accountId = 1;
request.requestTime = new Date().getTime();
request.filename = 'test.csv';
request.errors = []; request.errors = [];
const valdationObject = plainToClass( const valdationObject = plainToClass(
@ -351,18 +367,36 @@ describe('UsersController', () => {
expect(errors.length).toBe(0); 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 () => { it('エラーが存在するリクエストが成功する', async () => {
const request = new PostMultipleImportsCompleteRequest(); const request = new PostMultipleImportsCompleteRequest();
request.accountId = 1; request.accountId = 1;
request.requestTime = new Date().getTime();
request.filename = 'test.csv';
request.errors = [ request.errors = [
{ {
name: 'namae', name: 'namae',
email: 'hogehoge@example.com', line: 1,
errorCode: 'E1101', errorCode: 'E1101',
}, },
{ {
name: 'namae', name: 'namae',
email: 'hogehoge@example.com', line: 1,
errorCode: 'E1101', errorCode: 'E1101',
}, },
]; ];
@ -379,14 +413,16 @@ describe('UsersController', () => {
it('名前が足りないエラーがある場合、バリデーションエラーが発生する', async () => { it('名前が足りないエラーがある場合、バリデーションエラーが発生する', async () => {
const request = { const request = {
accountId: 1, accountId: 1,
filename: 'test.csv',
requestTime: new Date().getTime(),
errors: [ errors: [
{ {
email: 'hogehoge@example.com', line: 1,
errorCode: 'E1101', errorCode: 'E1101',
}, },
{ {
name: 'namae', name: 'namae',
email: 'hogehoge@example.com', line: 1,
errorCode: 'E1101', errorCode: 'E1101',
}, },
], ],
@ -398,12 +434,14 @@ describe('UsersController', () => {
); );
const errors = await validate(valdationObject); const errors = await validate(valdationObject);
expect(errors.length).toBeGreaterThan(0); expect(errors.length).toBe(1);
}); });
it('emailが足りないエラーがある場合、バリデーションエラーが発生する', async () => { it('行指定が足りないエラーがある場合、バリデーションエラーが発生する', async () => {
const request = { const request = {
accountId: 1, accountId: 1,
filename: 'test.csv',
requestTime: new Date().getTime(),
errors: [ errors: [
{ {
name: 'namae', name: 'namae',
@ -411,7 +449,7 @@ describe('UsersController', () => {
}, },
{ {
name: 'namae', name: 'namae',
email: 'hogehoge@example.com', line: 1,
errorCode: 'E1101', errorCode: 'E1101',
}, },
], ],
@ -423,20 +461,22 @@ describe('UsersController', () => {
); );
const errors = await validate(valdationObject); const errors = await validate(valdationObject);
expect(errors.length).toBeGreaterThan(0); expect(errors.length).toBe(1);
}); });
it('errorCodeが足りないエラーがある場合、バリデーションエラーが発生する', async () => { it('errorCodeが足りないエラーがある場合、バリデーションエラーが発生する', async () => {
const request = { const request = {
accountId: 1, accountId: 1,
filename: 'test.csv',
requestTime: new Date().getTime(),
errors: [ errors: [
{ {
name: 'namae', name: 'namae',
email: 'hogehoge@example.com', line: 1,
}, },
{ {
name: 'namae', name: 'namae',
email: 'hogehoge@example.com', line: 1,
errorCode: 'E1101', errorCode: 'E1101',
}, },
], ],
@ -448,21 +488,23 @@ describe('UsersController', () => {
); );
const errors = await validate(valdationObject); const errors = await validate(valdationObject);
expect(errors.length).toBeGreaterThan(0); expect(errors.length).toBe(1);
}); });
it('名前が空のエラーがある場合、バリデーションエラーが発生する', async () => { it('名前が空のエラーがある場合、バリデーションエラーが発生する', async () => {
const request = { const request = {
accountId: 1, accountId: 1,
filename: 'test.csv',
requestTime: new Date().getTime(),
errors: [ errors: [
{ {
name: '', name: '',
email: 'hogehoge@example.com', line: 1,
errorCode: 'E1101', errorCode: 'E1101',
}, },
{ {
name: 'namae', name: 'namae',
email: 'hogehoge@example.com', line: 1,
errorCode: 'E1101', errorCode: 'E1101',
}, },
], ],
@ -474,20 +516,21 @@ describe('UsersController', () => {
); );
const errors = await validate(valdationObject); const errors = await validate(valdationObject);
expect(errors.length).toBeGreaterThan(0); expect(errors.length).toBe(1);
}); });
it('emailが空のエラーがある場合、バリデーションエラーが発生する', async () => { it('行数が空のエラーがある場合、バリデーションエラーが発生する', async () => {
const request = { const request = {
accountId: 1, accountId: 1,
filename: 'test.csv',
requestTime: new Date().getTime(),
errors: [ errors: [
{ {
name: 'namae', name: 'namae',
email: '',
errorCode: 'E1101', errorCode: 'E1101',
}, },
{ {
name: 'namae', name: 'namae',
email: 'hogehoge@example.com', line: 1,
errorCode: 'E1101', errorCode: 'E1101',
}, },
], ],
@ -499,20 +542,22 @@ describe('UsersController', () => {
); );
const errors = await validate(valdationObject); const errors = await validate(valdationObject);
expect(errors.length).toBeGreaterThan(0); expect(errors.length).toBe(1);
}); });
it('emailが空のエラーがある場合、バリデーションエラーが発生する', async () => { it('エラーコードが空のエラーがある場合、バリデーションエラーが発生する', async () => {
const request = { const request = {
accountId: 1, accountId: 1,
filename: 'test.csv',
requestTime: new Date().getTime(),
errors: [ errors: [
{ {
name: 'namae', name: 'namae',
email: 'hogehoge@example.com', line: 1,
errorCode: '', errorCode: '',
}, },
{ {
name: 'namae', name: 'namae',
email: 'hogehoge@example.com', line: 1,
errorCode: 'E1101', errorCode: 'E1101',
}, },
], ],
@ -524,7 +569,7 @@ describe('UsersController', () => {
); );
const errors = await validate(valdationObject); const errors = await validate(valdationObject);
expect(errors.length).toBeGreaterThan(0); expect(errors.length).toBe(1);
}); });
}); });
}); });