Skip to content
Snippets Groups Projects
Commit e4f34f27 authored by OZGCloud's avatar OZGCloud
Browse files

OZG-2966 OZG-3098 create ngrx for binaryFile; implement download file as pdf

parent 727c51fc
No related branches found
No related tags found
No related merge requests found
export * from './lib/+state/binary-file.actions';
export * from './lib/+state/binary-file.reducer';
export * from './lib/binary-file-shared.module';
export * from './lib/binary-file.linkrel';
export * from './lib/binary-file.model';
export * from './lib/binary-file.service';
import { ApiError, ApiErrorAction, TypedActionCreatorWithProps } from '@goofy-client/tech-shared';
import { createAction, props } from '@ngrx/store';
import { TypedAction } from '@ngrx/store/src/models';
import { ResourceUri } from '@ngxp/rest';
export interface SaveBinaryFileAsPdfAction {
fileData: Blob
fileName: string
}
export interface DownloadBinaryFileAsPdfAction {
uri: ResourceUri
fileName: string,
successAction: () => DownloadBinaryFileSuccessAction & TypedAction<string>,
failureAction: (apiError: ApiError) => ApiErrorAction & TypedAction<string>,
}
export interface DownloadBinaryFileSuccessAction { }
export const downloadPdf: TypedActionCreatorWithProps<DownloadBinaryFileAsPdfAction> = createAction('[BinaryFile] Download pdf file', props<DownloadBinaryFileAsPdfAction>());
export const saveAsPdf: TypedActionCreatorWithProps<SaveBinaryFileAsPdfAction> = createAction('[BinaryFile/API] Save file as pdf', props<SaveBinaryFileAsPdfAction>());
\ No newline at end of file
import { TestBed } from '@angular/core/testing';
import faker from '@faker-js/faker';
import { TypedActionCreator } from '@goofy-client/tech-shared';
import { Mock, mock } from '@goofy-client/test-utils';
import { provideMockActions } from '@ngrx/effects/testing';
import { Action, createAction } from '@ngrx/store';
import { provideMockStore } from '@ngrx/store/testing';
import { ResourceUri } from '@ngxp/rest';
import { NxModule } from '@nrwl/angular';
import { hot } from 'jasmine-marbles';
import { cold } from 'jest-marbles';
import { Observable, of } from 'rxjs';
import { BinaryFileRepository } from '../binary-file.repository';
import { BinaryFileEffects } from './binary-file.effects';
import * as BinaryFileActions from './binary-file.actions';
describe('BinaryFileEffects', () => {
let actions: Observable<Action>;
let effects: BinaryFileEffects;
const binaryFileRepository: Mock<BinaryFileRepository> = mock(BinaryFileRepository);
beforeEach(() => {
TestBed.configureTestingModule({
imports: [NxModule.forRoot()],
providers: [
BinaryFileEffects,
provideMockActions(() => actions),
provideMockStore(),
{
provide: BinaryFileRepository,
useValue: binaryFileRepository
},
],
});
effects = TestBed.inject(BinaryFileEffects);
});
describe('downloadPdf', () => {
const uri: ResourceUri = faker.internet.url();
const fileName: string = faker.random.alphaNumeric();
const fileData: Blob = new Blob();
const downloadAsPdfSuccess: TypedActionCreator = createAction('[Test Action] Download Success');
//const downloadAsPdfFailure: TypedActionCreatorWithProps<ApiErrorAction>;// = createAction('[BinaryFile/Test] Download Failure', props<ApiErrorAction>());
const downloadPdfAction = BinaryFileActions.downloadPdf({ successAction: downloadAsPdfSuccess, failureAction: null, fileName, uri });
it('should call repository', () => {
actions = hot('-a', { a: downloadPdfAction });
effects.downloadPdf$.subscribe(() => {
expect(binaryFileRepository.downloadPdf).toHaveBeenCalledWith(uri);
});
});
it('should return actions on success', () => {
binaryFileRepository.downloadPdf.mockReturnValue(of(fileData));
actions = hot('-a', { a: downloadPdfAction });
const expected = cold('-(bc)', {
b: BinaryFileActions.saveAsPdf({ fileName, fileData }),
c: downloadAsPdfSuccess()
});
expect(effects.downloadPdf$).toBeObservable(expected);
});
it('should return actions on failure', () => {
})
});
describe('saveAsPdf', () => {
const fileName: string = faker.random.alphaNumeric();
const fileData: Blob = new Blob();
it('should save file', () => {
effects.save = jest.fn();
actions = hot('a', { a: BinaryFileActions.saveAsPdf({ fileData, fileName }) });
effects.saveAsPdf$.subscribe(() => {
expect(effects.save).toHaveBeenCalledWith(fileData, fileName);
})
})
})
});
import { Injectable } from '@angular/core';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { mergeMap, switchMap, tap } from 'rxjs/operators';
import { BinaryFileRepository } from '../binary-file.repository';
import * as saveAs from 'file-saver';
import * as BinaryFileActions from './binary-file.actions';
import { DownloadBinaryFileAsPdfAction, SaveBinaryFileAsPdfAction } from './binary-file.actions';
@Injectable()
export class BinaryFileEffects {
constructor(private readonly actions$: Actions, private readonly binaryFileRepository: BinaryFileRepository) { }
downloadPdf$ = createEffect(() =>
this.actions$.pipe(
ofType(BinaryFileActions.downloadPdf),
switchMap((action: DownloadBinaryFileAsPdfAction) => this.binaryFileRepository.downloadPdf(action.uri).pipe(
mergeMap((fileData: Blob) => [BinaryFileActions.saveAsPdf({ fileData, fileName: action.fileName }), action.successAction()])
//catchError(error => of(action.failureAction(getApiErrorFromHttpErrorResponse(error))))
))
)
);
saveAsPdf$ = createEffect(() =>
this.actions$.pipe(
ofType(BinaryFileActions.saveAsPdf),
tap((action: SaveBinaryFileAsPdfAction) => this.save(action.fileData, action.fileName))
), { dispatch: false })
save(fileData: Blob, name: string): void {
saveAs(fileData, name);
}
}
\ No newline at end of file
import { Action, createReducer } from '@ngrx/store';
export const BINARY_FILE_FEATURE_KEY = 'BinaryFileState';
export interface BinaryFileState { }
export interface BinaryFilePartialState {
readonly [BINARY_FILE_FEATURE_KEY]: BinaryFileState;
}
export const initialBinaryFileState: BinaryFileState = {};
const reducer = createReducer(initialBinaryFileState);
export function binaryFileReducer(state: BinaryFileState, action: Action) {
return reducer(state, action);
}
\ No newline at end of file
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { EffectsModule } from '@ngrx/effects';
import { StoreModule } from '@ngrx/store';
import { BinaryFileEffects } from './+state/binary-file.effects';
import * as fromBinaryFile from './+state/binary-file.reducer';
@NgModule({
imports: [CommonModule],
imports: [
CommonModule,
StoreModule.forFeature(
fromBinaryFile.BINARY_FILE_FEATURE_KEY,
fromBinaryFile.binaryFileReducer
),
EffectsModule.forFeature([BinaryFileEffects]),
]
})
export class BinaryFileSharedModule { }
......@@ -7,7 +7,7 @@ import { cold, hot } from 'jest-marbles';
import { DummyLinkRel } from 'libs/tech-shared/test/dummy';
import { createDummyListResource, createDummyResource } from 'libs/tech-shared/test/resource';
import { of } from 'rxjs';
import { BinaryFileRepository, GetRequestOptions } from './binary-file.repository';
import { BinaryFileRepository, ContentType, GetRequestOptions } from './binary-file.repository';
describe('BinaryFileRepository', () => {
let repository: BinaryFileRepository;
......@@ -96,14 +96,61 @@ describe('BinaryFileRepository', () => {
function getExpectedRequestOptions(): HttpHeaders {
let headers = new HttpHeaders();
headers = headers.set('Accept', ['application/*', 'images/*']);
headers = headers.set('Accept', [ContentType.APPLICATION_ALL, ContentType.IMAGES_ALL]);
return headers;
}
})
describe('downloadPdf', () => {
const blob = {};
const uri: ResourceUri = faker.internet.url();
beforeEach(() => {
httpClient.get.mockReturnValue(hot('a', { a: blob }));
})
it('should call httpClient', () => {
const requestOptions = {};
repository.buildPdfRequestOptions = jest.fn();
(<any>repository.buildPdfRequestOptions).mockReturnValue(requestOptions);
repository.downloadPdf(uri);
expect(httpClient.get).toHaveBeenCalledWith(uri, requestOptions);
})
it('should return value', () => {
const result = repository.downloadPdf(uri);
expect(result).toBeObservable(cold('b', { b: blob }));
})
describe('buildPdfRequestOptions', () => {
it('should return httpHeaders', () => {
const result: GetRequestOptions = repository.buildPdfRequestOptions();
expect(result.responseType).toEqual('blob');
})
it('should return responseType', () => {
const result: GetRequestOptions = repository.buildPdfRequestOptions();
expect(result.headers).toEqual(getExpectedRequestOptions());
})
})
function getExpectedRequestOptions(): HttpHeaders {
let headers = new HttpHeaders();
headers = headers.set('Accept', [ContentType.APPLICATION_PDF]);
return headers;
}
})
describe('get file', () => {
const uri: ResourceUri = getUrl(createDummyResource());
const uri: ResourceUri = faker.internet.url();
it('should call repository factory', () => {
repository.getFile(uri);
......@@ -139,21 +186,4 @@ describe('BinaryFileRepository', () => {
expect(resourceWrapper.get).toHaveBeenCalledWith(DummyLinkRel.DUMMY);
})
})
describe('get file', () => {
const uri: ResourceUri = faker.internet.url();
it('should call repository factory', () => {
repository.getFile(uri);
expect(resourceFactory.fromId).toHaveBeenCalledWith(uri);
})
it('should call repository wrapper', () => {
repository.getFile(uri);
expect(resourceWrapper.get).toHaveBeenCalled();
})
})
})
\ No newline at end of file
......@@ -14,16 +14,32 @@ export class BinaryFileRepository {
formData.append('file', file, file.name);
return this.httpClient.post(getUrl(resource, linkRel), formData, { observe: 'response' })
return this.httpClient.post(getUrl(resource, linkRel), formData, { observe: 'response' });
}
public download(fileResource: Resource, linkRel: string): Observable<Blob> {
return this.httpClient.get<Blob>(getUrl(fileResource, linkRel), this.buildRequestOptions());
return this.doDownload(getUrl(fileResource, linkRel), this.buildRequestOptions());
}
buildRequestOptions(): GetRequestOptions {
return this.buildBaseRequestOptions([ContentType.APPLICATION_ALL, ContentType.IMAGES_ALL]);
}
public downloadPdf(uri: ResourceUri): Observable<Blob> {
return this.doDownload(uri, this.buildPdfRequestOptions());
}
private doDownload(uri: ResourceUri, requestOptions: GetRequestOptions): Observable<Blob> {
return this.httpClient.get<Blob>(uri, requestOptions);
}
buildPdfRequestOptions(): GetRequestOptions {
return this.buildBaseRequestOptions([ContentType.APPLICATION_PDF]);
}
buildBaseRequestOptions(contentTypes: ContentType[]): GetRequestOptions {
let headers = new HttpHeaders();
headers = headers.set('Accept', ['application/*', 'images/*']);
headers = headers.set('Accept', contentTypes);
return { headers, responseType: 'blob' as 'json' };
}
......@@ -37,6 +53,12 @@ export class BinaryFileRepository {
}
export interface GetRequestOptions {
headers?: HttpHeaders | { [header: string]: string | string[] };
responseType?: 'json';
headers: HttpHeaders | { [header: string]: string | string[] };
responseType: 'json';
}
export enum ContentType {
APPLICATION_PDF = 'application/pdf',
IMAGES_ALL = 'images/*',
APPLICATION_ALL = 'application/*'
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment