Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
202 changes: 28 additions & 174 deletions apps/ftu-ui/src/app/app.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { MatDialog, MatDialogRef } from '@angular/material/dialog';
import { dispatch, dispatch$, select$, selectQuerySnapshot, selectSnapshot } from '@hra-ui/cdk/injectors';
import { ActionContext } from '@ngxs/store';
import { mock } from 'jest-mock-extended';
import { ReplaySubject, of } from 'rxjs';
import { of, Subject } from 'rxjs';
import { Shallow } from 'shallow-render';
import { AppComponent } from './app.component';
import { AppComponent, filterUndefined } from './app.component';

jest.mock('@hra-ui/cdk/injectors');

Expand All @@ -14,7 +13,6 @@ describe('AppComponent', () => {
const dispatchSpy = jest.fn();

let shallow: Shallow<AppComponent>;
let actions: ReplaySubject<ActionContext>;

beforeEach(() => {
jest.mocked(selectSnapshot).mockReturnValue(jest.fn());
Expand All @@ -24,181 +22,37 @@ describe('AppComponent', () => {
jest.mocked(select$).mockReturnValue(of({}));
dialog.open.mockReturnValue(postRef);

actions = new ReplaySubject(1);

// shallow = new Shallow(AppComponent, appConfig)
// .replaceModule(RouterModule, RouterTestingModule)
// .replaceModule(BrowserAnimationsModule, NoopAnimationsModule)
// .dontMock(MatDialogModule, FTU_DATA_IMPL_ENDPOINTS, ENVIRONMENT_INITIALIZER)
// .provideMock(
// {
// provide: MatDialog,
// useValue: dialog,
// },
// {
// provide: Actions,
// useValue: actions,
// },
// );
shallow = new Shallow(AppComponent);
});

afterEach(() => jest.clearAllMocks());

describe('AppComponent', () => {
it('passes a dummy test', () => {
expect(true).toBeTruthy();
describe('filterUndefined utility function', () => {
it('should filter out undefined values from observable', (done) => {
const source = new Subject<string | undefined>();
const results: string[] = [];

source.pipe(filterUndefined()).subscribe({
next: (value) => results.push(value),
complete: () => {
expect(results).toEqual(['value1', 'value2']);
done();
},
});

source.next(undefined);
source.next('value1');
source.next(undefined);
source.next('value2');
source.next(undefined);
source.complete();
});
});

// it('should create component', async () => {
// await expect(shallow.render()).resolves.toBeDefined();
// });

// describe('.selectedIllustration', () => {
// const iri = 'https://foo.bar/';
// const illustration: RawIllustration = {
// '@id': iri as Iri,
// label: '',
// organ_id: '',
// organ_label: '',
// representation_of: '',
// mapping: [],
// illustration_files: [],
// };

// it('accepts an iri string', async () => {
// await shallow.render({ bind: { selectedIllustration: iri } });
// expect(dispatchSpy).toHaveBeenCalledWith(LinkIds.ExploreFTU, expect.anything());
// });

// it('accepts an illustration object', async () => {
// await shallow.render({ bind: { selectedIllustration: illustration } });
// expect(dispatchSpy).toHaveBeenCalledWith(LinkIds.ExploreFTU, expect.anything());
// });

// it('automatically selects a tissue if not provided', async () => {
// jest.mocked(select$).mockReturnValue(
// of({
// organ: { children: ['tissue'] },
// }),
// );
// await shallow.render();

// expect(dispatchSpy).toHaveBeenCalledWith(LinkIds.ExploreFTU, expect.anything());
// });
// });

// describe('.summaries', () => {
// it('resets the state when changed', async () => {
// const spy = jest.fn();
// jest.mocked(dispatch).mockImplementation((type) => (type === ActiveFtuActions.Clear ? spy : dispatchSpy));

// const { bindings, fixture } = await shallow.render({ bind: { summaries: '' } });
// spy.mockClear();
// bindings.summaries = 'url/to/summaries';
// fixture.detectChanges();
// expect(spy).toHaveBeenCalledTimes(1);
// });
// });

// describe('.baseHref', () => {
// it('updates the base href for the app', async () => {
// await shallow.render({ bind: { baseHref: 'test' } });
// expect(dispatchSpy).toHaveBeenCalledWith('test');
// });
// });

// describe('.cellHover', () => {
// it('emits node hover events', async () => {
// const node = {
// source: { id: 'abc' },
// };
// const events = from([node, undefined]);
// jest.mocked(select$).mockImplementation((fn) => (fn === IllustratorSelectors.selectedOnHovered ? events : of()));

// const { instance } = await shallow.render();
// const output = await firstValueFrom(instance.cellHover.pipe(take(2), toArray()));
// expect(output).toEqual([node.source, undefined]);
// });
// });

// describe('.cellClick', () => {
// it('emits node click events', async () => {
// const node = {
// source: { id: 'abc' },
// } as unknown as IllustrationMappingItem;
// const context: ActionContext = {
// status: ActionStatus.Dispatched,
// action: new IllustratorActions.SetClicked(node),
// };

// const { instance } = await shallow.render();
// const output = firstValueFrom(instance.cellClick.pipe(take(1)));
// actions.next(context);
// expect(await output).toEqual(node.source);
// });
// });

// it('should show dailog box if sceen size is less than 480px', async () => {
// const { instance } = await shallow.render();
// global.innerWidth = 400;
// instance.onWindowResize();
// expect(dialog.open).toHaveBeenCalled();
// });

// it('should load links from YAML URL', async () => {
// const { instance } = await shallow.render();
// const url = 'mock-url';
// instance.appLinks = url;
// expect(dispatch).toHaveBeenCalled();
// });

// it('should load resources from YAML URL', async () => {
// const { instance } = await shallow.render();
// const url = 'mock-url';
// instance.appResources = url;
// expect(dispatch).toHaveBeenCalled();
// });

// it('should navigate to organ based on provided IRI', async () => {
// jest.mocked(dispatch).mockReturnValue((TestId) => new LinkRegistryActions.Navigate(TestId));
// const { instance } = await shallow.render();
// instance.selectedIllustration = 'test-id';
// expect(dispatch).toHaveBeenCalledWith(LinkRegistryActions.Navigate);
// });

// it('should load default iri when no iri present', async () => {
// jest.mocked(select$).mockReturnValue(of({ test1: { children: ['testUrl'] } }));
// await shallow.render({ bind: { appLinks: '', appResources: '', selectedIllustration: '' } });
// expect(dispatch).toHaveBeenCalledWith(LinkRegistryActions.Navigate);
// });

// it('should reset and reload datasets on change of datasetUrl', async () => {
// const { instance } = await shallow.render({
// bind: {
// appLinks: '',
// appResources: '',
// selectedIllustration: '',
// datasets: '',
// illustrations: '',
// summaries: '',
// },
// });
// instance.datasets = 'tempUrl';
// expect(dispatch$).toHaveBeenCalledWith(LinkRegistryActions.LoadFromYaml);
// expect(dispatch).toHaveBeenCalledWith(TissueLibraryActions.Load);
// });
// });

// describe('initFactory()', () => {
// const dispatcher = jest.fn().mockReturnValue(of(undefined));
// jest.mocked(dispatchAction$).mockReturnValue(dispatcher);

// afterEach(() => jest.clearAllMocks());

// it('should dispatch actions', () => {
// const init = initFactory();
// init();
// expect(dispatcher).toHaveBeenCalled();
// });
describe('AppComponent', () => {
it('should create test setup', () => {
expect(shallow).toBeDefined();
expect(dispatchSpy).toBeDefined();
});
});
});
2 changes: 1 addition & 1 deletion apps/ftu-ui/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ const UPDATE_ALL_SELECTORS: UpdateSelectors = {
* Creates an observable operator function that remove undefined values from a stream
* @returns Observable operator function
*/
function filterUndefined<T>(): OperatorFunction<T | undefined, T> {
export function filterUndefined<T>(): OperatorFunction<T | undefined, T> {
return filter((value): value is T => value !== undefined);
}

Expand Down
44 changes: 42 additions & 2 deletions apps/ftu-ui/src/app/pages/ftu-page/ftu.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,62 @@
import { ActivatedRoute } from '@angular/router';
import { dispatch, injectDestroy$, selectSnapshot } from '@hra-ui/cdk/injectors';
import { FtuFullScreenService } from '@hra-ui/ftu-ui-components';
import { EMPTY, of } from 'rxjs';
import { signal, TemplateRef } from '@angular/core';
import { Shallow } from 'shallow-render';
import { FtuComponent } from './ftu.component';

jest.mock('@hra-ui/cdk/injectors');
jest.mocked(injectDestroy$).mockReturnValue(EMPTY);
jest.mocked(dispatch).mockReturnValue(jest.fn());

describe('AppComponent', () => {
describe('FtuComponent', () => {
let shallow: Shallow<FtuComponent>;
let mockFullscreenService: FtuFullScreenService;

beforeEach(() => {
shallow = new Shallow(FtuComponent).mock(ActivatedRoute, { queryParams: of({ id: 'abc' }) });
// Create mock fullscreen service
mockFullscreenService = {
isFullscreen: signal<boolean>(false),
fullscreentabIndex: signal<number>(0),
} as unknown as FtuFullScreenService;

shallow = new Shallow(FtuComponent)
.mock(ActivatedRoute, { queryParams: of({ id: 'abc' }) })
.mock(FtuFullScreenService, mockFullscreenService);
jest.mocked(selectSnapshot).mockReturnValue(jest.fn());
});

it('should create component', async () => {
expect(shallow.render()).resolves.toBeDefined();
});

it('should close fullscreen mode when closefullscreen() is called', async () => {
const { instance } = await shallow.render();

(
instance as unknown as {
fullscreenService?: FtuFullScreenService;
}
).fullscreenService = mockFullscreenService;

mockFullscreenService.isFullscreen.set(true);
expect(mockFullscreenService.isFullscreen()).toBe(true);

instance.closefullscreen();

expect(mockFullscreenService.isFullscreen()).toBe(false);
});

it('should set sourceListTemplate when setSourceList() is called', async () => {
const { instance } = await shallow.render();

const mockTemplateRef = {} as TemplateRef<unknown>;

expect(instance.sourceListTemplate).toBeNull();

instance.setSourceList(mockTemplateRef);

expect(instance.sourceListTemplate).toBe(mockTemplateRef);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,11 @@ describe('AppComponent', () => {
it('should create component', async () => {
expect(shallow.render()).resolves.toBeDefined();
});

it('should use appLink2 for EBI link', async () => {
const { instance } = await shallow.render({
bind: { appLink1: 'https://custom-kpmp.org', appLink2: 'https://custom-ebi.ac.uk' },
});
expect(instance['ebiLink']()).toBe('https://custom-ebi.ac.uk');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,5 @@ export class LandingComponent {
/**
* Computed property that returns the EBI link.
*/
protected readonly ebiLink = computed(() => this.appLink1() ?? EBI_LINK);
protected readonly ebiLink = computed(() => this.appLink2() ?? EBI_LINK);
}