Skip to content

Commit

Permalink
Added loading the scan types via the message system [#643]
Browse files Browse the repository at this point in the history
  • Loading branch information
mcpierce committed Mar 16, 2021
1 parent c0b30b0 commit 8f2750a
Show file tree
Hide file tree
Showing 15 changed files with 556 additions and 23 deletions.
Expand Up @@ -18,14 +18,11 @@

package org.comixedproject.controller.comic;

import java.util.List;
import lombok.extern.log4j.Log4j2;
import org.comixedproject.auditlog.AuditableEndpoint;
import org.comixedproject.model.comic.ScanType;
import org.comixedproject.service.comic.ScanTypeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.web.bind.annotation.RestController;

/**
Expand All @@ -37,17 +34,18 @@
@RestController
@Log4j2
public class ScanTypeController {
private static final String LOAD_SCAN_TYPES = "load.scan-types";
public static final String ADD_SCAN_TYPE_QUEUE = "/topic/scan-type.add";

@Autowired private ScanTypeService scanTypeService;
@Autowired private SimpMessagingTemplate messagingTemplate;

/**
* Retrieves the list of all scan types.
*
* @return the scan type list
*/
@GetMapping(value = "/api/comics/scantypes", produces = MediaType.APPLICATION_JSON_VALUE)
@AuditableEndpoint
public List<ScanType> getScanTypes() {
/** Retrieves the list of all scan types and publishes them. */
@MessageMapping(LOAD_SCAN_TYPES)
public void getScanTypes() {
log.info("Getting all scan types");
return this.scanTypeService.getAll();
this.scanTypeService
.getAll()
.forEach(scanType -> this.messagingTemplate.convertAndSend(ADD_SCAN_TYPE_QUEUE, scanType));
}
}
@@ -1,3 +1,21 @@
/*
* ComiXed - A digital comic book library management application.
* Copyright (C) 2021, The ComiXed Project
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses>
*/

package org.comixedproject.messaging;

import lombok.extern.log4j.Log4j2;
Expand Down
Expand Up @@ -18,9 +18,9 @@

package org.comixedproject.controller.comic;

import static junit.framework.TestCase.assertNotNull;
import static junit.framework.TestCase.assertSame;
import static org.comixedproject.controller.comic.ScanTypeController.ADD_SCAN_TYPE_QUEUE;

import java.util.ArrayList;
import java.util.List;
import org.comixedproject.model.comic.ScanType;
import org.comixedproject.service.comic.ScanTypeService;
Expand All @@ -30,22 +30,27 @@
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.messaging.simp.SimpMessagingTemplate;

@RunWith(MockitoJUnitRunner.class)
public class ScanTypeControllerTest {
@InjectMocks private ScanTypeController controller;
@Mock private ScanTypeService scanTypeService;
@Mock private List<ScanType> scanTypeList;
@Mock private SimpMessagingTemplate messagingTemplate;
@Mock private ScanType scanType;

private List<ScanType> scanTypeList = new ArrayList<ScanType>();

@Test
public void testGetScanTypes() {
Mockito.when(scanTypeService.getAll()).thenReturn(scanTypeList);
scanTypeList.add(scanType);

final List<ScanType> result = controller.getScanTypes();
Mockito.when(scanTypeService.getAll()).thenReturn(scanTypeList);

assertNotNull(result);
assertSame(scanTypeList, result);
controller.getScanTypes();

Mockito.verify(scanTypeService, Mockito.times(1)).getAll();
Mockito.verify(messagingTemplate, Mockito.times(scanTypeList.size()))
.convertAndSend(ADD_SCAN_TYPE_QUEUE, scanType);
}
}
27 changes: 27 additions & 0 deletions comixed-web/src/app/library/actions/scan-type.actions.ts
@@ -0,0 +1,27 @@
/*
* ComiXed - A digital comic book library management application.
* Copyright (C) 2021, The ComiXed Project
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses>
*/

import { createAction, props } from '@ngrx/store';
import { ScanType } from '@app/library';

export const loadScanTypes = createAction('[Scan Type] Load all scan types');

export const addScanType = createAction(
'[Scan Type] A scan type was received',
props<{ scanType: ScanType }>()
);
52 changes: 52 additions & 0 deletions comixed-web/src/app/library/effects/scan-type.effects.spec.ts
@@ -0,0 +1,52 @@
/*
* ComiXed - A digital comic book library management application.
* Copyright (C) 2021, The ComiXed Project
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses>
*/

import { TestBed } from '@angular/core/testing';
import { provideMockActions } from '@ngrx/effects/testing';
import { Observable } from 'rxjs';

import { ScanTypeEffects } from './scan-type.effects';
import { ScanTypeService } from '@app/library/services/scan-type.service';

describe('ScanTypeEffects', () => {
const actions$: Observable<any> = null;
let effects: ScanTypeEffects;
let scanTypeService: jasmine.SpyObj<ScanTypeService>;

beforeEach(() => {
TestBed.configureTestingModule({
providers: [
ScanTypeEffects,
provideMockActions(() => actions$),
{
provide: ScanTypeService,
useValue: {}
}
]
});

effects = TestBed.inject(ScanTypeEffects);
scanTypeService = TestBed.inject(
ScanTypeService
) as jasmine.SpyObj<ScanTypeService>;
});

it('should be created', () => {
expect(effects).toBeTruthy();
});
});
29 changes: 29 additions & 0 deletions comixed-web/src/app/library/effects/scan-type.effects.ts
@@ -0,0 +1,29 @@
/*
* ComiXed - A digital comic book library management application.
* Copyright (C) 2021, The ComiXed Project
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses>
*/

import { Injectable } from '@angular/core';
import { Actions } from '@ngrx/effects';
import { ScanTypeService } from '@app/library/services/scan-type.service';

@Injectable()
export class ScanTypeEffects {
constructor(
private actions$: Actions,
private scanTypeService: ScanTypeService
) {}
}
9 changes: 8 additions & 1 deletion comixed-web/src/app/library/index.ts
Expand Up @@ -44,6 +44,11 @@ import {
BlockedPageState,
reducer as blockedPageReducer
} from '@app/library/reducers/blocked-page.reducer';
import {
reducer as scanTypeReducer,
SCAN_TYPE_FEATURE_KEY,
ScanTypeState
} from '@app/library/reducers/scan-type.reducer';

export { Comic } from '@app/library/models/comic';
export { ComicCredit } from '@app/library/models/comic-credit';
Expand All @@ -70,6 +75,7 @@ export interface LibraryModuleState {
[LIBRARY_FEATURE_KEY]: LibraryState;
[SCRAPING_FEATURE_KEY]: ScrapingState;
[BLOCKED_PAGE_FEATURE_KEY]: BlockedPageState;
[SCAN_TYPE_FEATURE_KEY]: ScanTypeState;
}

export type ModuleState = LibraryModuleState;
Expand All @@ -80,5 +86,6 @@ export const reducers: ActionReducerMap<LibraryModuleState> = {
[COMIC_IMPORT_FEATURE_KEY]: libraryImportReducer,
[LIBRARY_FEATURE_KEY]: libraryReducer,
[SCRAPING_FEATURE_KEY]: scrapingReducer,
[BLOCKED_PAGE_FEATURE_KEY]: blockedPageReducer
[BLOCKED_PAGE_FEATURE_KEY]: blockedPageReducer,
[SCAN_TYPE_FEATURE_KEY]: scanTypeReducer
};
4 changes: 4 additions & 0 deletions comixed-web/src/app/library/library.constants.ts
Expand Up @@ -69,3 +69,7 @@ export const PAGE_SIZE_DEFAULT = 400;
export const PAGINATION_OPTIONS = [10, 25, 50, 100];
export const PAGINATION_PREFERENCE = 'preference.pagination';
export const PAGINATION_DEFAULT = PAGINATION_OPTIONS[0];

// messaging
export const LOAD_SCAN_TYPES_MESSAGE = '/comixed/load.scan-types';
export const SCAN_TYPE_ADD_QUEUE = '/topic/scan-type.add';
9 changes: 8 additions & 1 deletion comixed-web/src/app/library/library.module.ts
Expand Up @@ -99,6 +99,11 @@ import { BlockedPageEffects } from '@app/library/effects/blocked-page.effects';
import { ComicPageComponent } from '@app/library/components/comic-page/comic-page.component';
import { ComicDetailCardComponent } from '@app/library/components/comic-detail-card/comic-detail-card.component';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import {
SCAN_TYPE_FEATURE_KEY,
reducer as scanTypeReducer
} from '@app/library/reducers/scan-type.reducer';
import { ScanTypeEffects } from '@app/library/effects/scan-type.effects';

@NgModule({
declarations: [
Expand Down Expand Up @@ -144,12 +149,14 @@ import { MatProgressBarModule } from '@angular/material/progress-bar';
StoreModule.forFeature(LIBRARY_FEATURE_KEY, libraryReducer),
StoreModule.forFeature(SCRAPING_FEATURE_KEY, scrapingReducer),
StoreModule.forFeature(BLOCKED_PAGE_FEATURE_KEY, blockedPageReducer),
StoreModule.forFeature(SCAN_TYPE_FEATURE_KEY, scanTypeReducer),
EffectsModule.forFeature([
DisplayEffects,
ComicImportEffects,
LibraryEffects,
ScrapingEffects,
BlockedPageEffects
BlockedPageEffects,
ScanTypeEffects
]),
MatInputModule,
MatSelectModule,
Expand Down
71 changes: 71 additions & 0 deletions comixed-web/src/app/library/reducers/scan-type.reducer.spec.ts
@@ -0,0 +1,71 @@
/*
* ComiXed - A digital comic book library management application.
* Copyright (C) 2021, The ComiXed Project
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses>
*/

import { initialState, reducer, ScanTypeState } from './scan-type.reducer';
import { SCAN_TYPE_1 } from '@app/library/library.fixtures';
import {
addScanType,
loadScanTypes
} from '@app/library/actions/scan-type.actions';

describe('ScanType Reducer', () => {
const SCAN_TYPE = SCAN_TYPE_1;

let state: ScanTypeState;

beforeEach(() => {
state = { ...initialState };
});

describe('the initial state', () => {
beforeEach(() => {
state = reducer({ ...state }, {} as any);
});

it('has no scan types', () => {
expect(state.types).toEqual([]);
});
});

describe('loading the scan types', () => {
beforeEach(() => {
state = reducer({ ...state, initialized: true }, loadScanTypes());
});

it('clears the initialized flag', () => {
expect(state.initialized).toBeFalse();
});
});

describe('receiving a scan type', () => {
beforeEach(() => {
state = reducer(
{ ...state, initialized: false, types: [] },
addScanType({ scanType: SCAN_TYPE })
);
});

it('sets the initialized flag', () => {
expect(state.initialized).toBeTrue();
});

it('adds the scan type', () => {
expect(state.types).toContain(SCAN_TYPE);
});
});
});

0 comments on commit 8f2750a

Please sign in to comment.