90978: Fix e2e tests failing due to interactions before page fully loaded

Now that we use initialNavigation: 'enabledBlocking', pages can appear to be loaded before some functionality is fully active.
In some cases this trips up Cypress, and it tries to interact with the app too soon.

We address this by introducing a new dsBrowserOnly pipe in order to defer the data-test attributes Cypress relies on to CSR.
This commit is contained in:
Yura Bondarenko
2022-04-27 09:06:55 +02:00
parent 22d5643d8b
commit d69a02e6cc
32 changed files with 123 additions and 43 deletions

View File

@@ -65,7 +65,7 @@ describe('My DSpace page', () => {
cy.visit('/mydspace');
// Open the New Submission dropdown
cy.get('#dropdownSubmission').click();
cy.get('button[data-test="submission-dropdown"]').click();
// Click on the "Item" type in that dropdown
cy.get('#entityControlsDropdownMenu button[title="none"]').click();
@@ -98,7 +98,7 @@ describe('My DSpace page', () => {
const id = subpaths[2];
// Click the "Save for Later" button to save this submission
cy.get('button#saveForLater').click();
cy.get('ds-submission-form-footer [data-test="save-for-later"]').click();
// "Save for Later" should send us to MyDSpace
cy.url().should('include', '/mydspace');
@@ -122,7 +122,7 @@ describe('My DSpace page', () => {
cy.url().should('include', '/workspaceitems/' + id + '/edit');
// Discard our new submission by clicking Discard in Submission form & confirming
cy.get('button#discard').click();
cy.get('ds-submission-form-footer [data-test="discard"]').click();
cy.get('button#discard_submit').click();
// Discarding should send us back to MyDSpace
@@ -135,7 +135,7 @@ describe('My DSpace page', () => {
cy.visit('/mydspace');
// Open the New Import dropdown
cy.get('#dropdownImport').click();
cy.get('button[data-test="import-dropdown"]').click();
// Click on the "Item" type in that dropdown
cy.get('#importControlsDropdownMenu button[title="none"]').click();

View File

@@ -24,7 +24,7 @@ describe('Search Page', () => {
// Click each filter toggle to open *every* filter
// (As we want to scan filter section for accessibility issues as well)
cy.get('.filter-toggle').click({ multiple: true });
cy.get('[data-test="filter-toggle"]').click({ multiple: true });
// Analyze <ds-search-page> for accessibility issues
testA11y(

View File

@@ -27,7 +27,7 @@
<a *ngIf="bitstreamDownloadUrl != null" [href]="bitstreamDownloadUrl"
class="btn btn-outline-primary btn-sm"
title="{{'item.edit.bitstreams.edit.buttons.download' | translate}}"
data-test="download-button">
[attr.data-test]="'download-button' | dsBrowserOnly">
<i class="fas fa-download fa-fw"></i>
</a>
<button [routerLink]="['/bitstreams/', bitstream.id, 'edit']" class="btn btn-outline-primary btn-sm"

View File

@@ -12,6 +12,7 @@ import { ResponsiveColumnSizes } from '../../../../shared/responsive-table-sizes
import { createSuccessfulRemoteDataObject$ } from '../../../../shared/remote-data.utils';
import { getBitstreamDownloadRoute } from '../../../../app-routing-paths';
import { By } from '@angular/platform-browser';
import { BrowserOnlyMockPipe } from '../../../../shared/testing/browser-only-mock.pipe';
let comp: ItemEditBitstreamComponent;
let fixture: ComponentFixture<ItemEditBitstreamComponent>;
@@ -72,7 +73,11 @@ describe('ItemEditBitstreamComponent', () => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot()],
declarations: [ItemEditBitstreamComponent, VarDirective],
declarations: [
ItemEditBitstreamComponent,
VarDirective,
BrowserOnlyMockPipe,
],
providers: [
{ provide: ObjectUpdatesService, useValue: objectUpdatesService }
], schemas: [

View File

@@ -11,6 +11,7 @@
<button class="btn btn-lg btn-outline-primary mt-1 ml-2" id="dropdownImport" ngbDropdownToggle
type="button" [disabled]="!(initialized$|async)"
attr.aria-label="{{'mydspace.new-submission-external' | translate}}"
[attr.data-test]="'import-dropdown' | dsBrowserOnly"
title="{{'mydspace.new-submission-external' | translate}}">
<i class="fa fa-file-import" aria-hidden="true"></i>
<span class="caret"></span>

View File

@@ -13,6 +13,7 @@ import { ResourceType } from '../../../core/shared/resource-type';
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
import { PageInfo } from '../../../core/shared/page-info.model';
import { RouterStub } from '../../../shared/testing/router.stub';
import { BrowserOnlyMockPipe } from '../../../shared/testing/browser-only-mock.pipe';
export function getMockEntityTypeService(): EntityTypeService {
const pageInfo = { elementsPerPage: 20, totalElements: 4, totalPages: 1, currentPage: 0 } as PageInfo;
@@ -83,7 +84,8 @@ describe('MyDSpaceNewExternalDropdownComponent test', () => {
],
declarations: [
MyDSpaceNewExternalDropdownComponent,
TestComponent
TestComponent,
BrowserOnlyMockPipe
],
providers: [
{ provide: EntityTypeService, useValue: getMockEmptyEntityTypeService() },
@@ -134,7 +136,8 @@ describe('MyDSpaceNewExternalDropdownComponent test', () => {
],
declarations: [
MyDSpaceNewExternalDropdownComponent,
TestComponent
TestComponent,
BrowserOnlyMockPipe,
],
providers: [
{ provide: EntityTypeService, useValue: getMockEntityTypeService() },

View File

@@ -9,6 +9,7 @@
<button class="btn btn-lg btn-primary mt-1 ml-2" id="dropdownSubmission" ngbDropdownToggle
type="button" [disabled]="!(initialized$|async)"
attr.aria-label="{{'mydspace.new-submission' | translate}}"
[attr.data-test]="'submission-dropdown' | dsBrowserOnly"
title="{{'mydspace.new-submission' | translate}}">
<i class="fa fa-plus-circle" aria-hidden="true"></i>
<span class="caret"></span>

View File

@@ -12,6 +12,7 @@ import { ItemType } from '../../../core/shared/item-relationships/item-type.mode
import { ResourceType } from '../../../core/shared/resource-type';
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
import { PageInfo } from '../../../core/shared/page-info.model';
import { BrowserOnlyMockPipe } from '../../../shared/testing/browser-only-mock.pipe';
export function getMockEntityTypeService(): EntityTypeService {
const type1: ItemType = {
@@ -87,7 +88,8 @@ describe('MyDSpaceNewSubmissionDropdownComponent test', () => {
],
declarations: [
MyDSpaceNewSubmissionDropdownComponent,
TestComponent
TestComponent,
BrowserOnlyMockPipe,
],
providers: [
{ provide: EntityTypeService, useValue: getMockEmptyEntityTypeService() },
@@ -138,7 +140,8 @@ describe('MyDSpaceNewSubmissionDropdownComponent test', () => {
],
declarations: [
MyDSpaceNewSubmissionDropdownComponent,
TestComponent
TestComponent,
BrowserOnlyMockPipe,
],
providers: [
{ provide: EntityTypeService, useValue: getMockEntityTypeService() },

View File

@@ -3,8 +3,8 @@
<form [formGroup]="searchForm" (ngSubmit)="onSubmit(searchForm.value)" autocomplete="on">
<input #searchInput [@toggleAnimation]="isExpanded" [attr.aria-label]="('nav.search' | translate)" name="query"
formControlName="query" type="text" placeholder="{{searchExpanded ? ('nav.search' | translate) : ''}}"
class="d-inline-block bg-transparent position-absolute form-control dropdown-menu-right p-1" data-test="header-search-box">
<a class="submit-icon" [routerLink]="" (click)="searchExpanded ? onSubmit(searchForm.value) : expand()" data-test="header-search-icon">
class="d-inline-block bg-transparent position-absolute form-control dropdown-menu-right p-1" [attr.data-test]="'header-search-box' | dsBrowserOnly">
<a class="submit-icon" [routerLink]="" (click)="searchExpanded ? onSubmit(searchForm.value) : expand()" [attr.data-test]="'header-search-icon' | dsBrowserOnly">
<em class="fas fa-search fa-lg fa-fw"></em>
</a>
</form>

View File

@@ -10,6 +10,7 @@ import { TranslateLoaderMock } from '../shared/mocks/translate-loader.mock';
import { SearchNavbarComponent } from './search-navbar.component';
import { PaginationServiceStub } from '../shared/testing/pagination-service.stub';
import { RouterTestingModule } from '@angular/router/testing';
import { BrowserOnlyMockPipe } from '../shared/testing/browser-only-mock.pipe';
describe('SearchNavbarComponent', () => {
let component: SearchNavbarComponent;
@@ -44,7 +45,10 @@ describe('SearchNavbarComponent', () => {
useClass: TranslateLoaderMock
}
})],
declarations: [SearchNavbarComponent],
declarations: [
SearchNavbarComponent,
BrowserOnlyMockPipe,
],
providers: [
{ provide: SearchService, useValue: mockSearchService }
]

View File

@@ -1,8 +1,8 @@
<ul class="navbar-nav" [ngClass]="{'mr-auto': (isXsOrSm$ | async)}">
<li *ngIf="!(isAuthenticated | async) && !(isXsOrSm$ | async) && (showAuth | async)" class="nav-item"
(click)="$event.stopPropagation();">
<div ngbDropdown #loginDrop display="dynamic" placement="bottom-right" class="d-inline-block" data-test="login-menu" @fadeInOut>
<a href="javascript:void(0);" class="dropdownLogin px-1 " [attr.aria-label]="'nav.login' |translate" (click)="$event.preventDefault()" ngbDropdownToggle>
<div ngbDropdown #loginDrop display="dynamic" placement="bottom-right" class="d-inline-block" @fadeInOut>
<a href="javascript:void(0);" class="dropdownLogin px-1 " [attr.aria-label]="'nav.login' |translate" (click)="$event.preventDefault()" [attr.data-test]="'login-menu' | dsBrowserOnly" ngbDropdownToggle>
{{ 'nav.login' | translate }}
</a>
<div class="loginDropdownMenu" [ngClass]="{'pl-3 pr-3': (loading | async)}" ngbDropdownMenu
@@ -17,9 +17,9 @@
{{ 'nav.login' | translate }}<span class="sr-only">(current)</span>
</a>
</li>
<li *ngIf="(isAuthenticated | async) && !(isXsOrSm$ | async) && (showAuth | async)" class="nav-item" data-test="user-menu">
<li *ngIf="(isAuthenticated | async) && !(isXsOrSm$ | async) && (showAuth | async)" class="nav-item">
<div ngbDropdown display="dynamic" placement="bottom-right" class="d-inline-block" @fadeInOut>
<a href="javascript:void(0);" role="button" [attr.aria-label]="'nav.logout' |translate" (click)="$event.preventDefault()" [title]="'nav.logout' | translate" class="px-1" ngbDropdownToggle>
<a href="javascript:void(0);" role="button" [attr.aria-label]="'nav.logout' |translate" (click)="$event.preventDefault()" [title]="'nav.logout' | translate" class="px-1" [attr.data-test]="'user-menu' | dsBrowserOnly" ngbDropdownToggle>
<i class="fas fa-user-circle fa-lg fa-fw"></i></a>
<div class="logoutDropdownMenu" ngbDropdownMenu [attr.aria-label]="'nav.logout' |translate">
<ds-user-menu></ds-user-menu>

View File

@@ -15,6 +15,7 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { AuthTokenInfo } from '../../core/auth/models/auth-token-info.model';
import { AuthService } from '../../core/auth/auth.service';
import { of } from 'rxjs';
import { BrowserOnlyMockPipe } from '../testing/browser-only-mock.pipe';
describe('AuthNavMenuComponent', () => {
@@ -77,7 +78,8 @@ describe('AuthNavMenuComponent', () => {
TranslateModule.forRoot()
],
declarations: [
AuthNavMenuComponent
AuthNavMenuComponent,
BrowserOnlyMockPipe
],
providers: [
{ provide: HostWindowService, useValue: window },

View File

@@ -8,6 +8,6 @@
</ng-container>
<div class="dropdown-divider"></div>
<a class="dropdown-item" *ngIf="canRegister$ | async" [routerLink]="[getRegisterRoute()]" data-test="register">{{"login.form.new-user" | translate}}</a>
<a class="dropdown-item" [routerLink]="[getForgotRoute()]" data-test="forgot">{{"login.form.forgot-password" | translate}}</a>
<a class="dropdown-item" *ngIf="canRegister$ | async" [routerLink]="[getRegisterRoute()]" [attr.data-test]="'register' | dsBrowserOnly">{{"login.form.new-user" | translate}}</a>
<a class="dropdown-item" [routerLink]="[getForgotRoute()]" [attr.data-test]="'forgot' | dsBrowserOnly">{{"login.form.forgot-password" | translate}}</a>
</div>

View File

@@ -10,7 +10,7 @@
placeholder="{{'login.form.email' | translate}}"
required
type="email"
data-test="email">
[attr.data-test]="'email' | dsBrowserOnly">
<label class="sr-only">{{"login.form.password" | translate}}</label>
<input [attr.aria-label]="'login.form.password' |translate"
autocomplete="off"
@@ -19,12 +19,12 @@
formControlName="password"
required
type="password"
data-test="password">
[attr.data-test]="'password' | dsBrowserOnly">
<div *ngIf="(error | async) && hasError" class="alert alert-danger" role="alert"
@fadeOut>{{ (error | async) | translate }}</div>
<div *ngIf="(message | async) && hasMessage" class="alert alert-info" role="alert"
@fadeOut>{{ (message | async) | translate }}</div>
<button class="btn btn-lg btn-primary btn-block mt-3" type="submit" data-test="login-button"
<button class="btn btn-lg btn-primary btn-block mt-3" type="submit" [attr.data-test]="'login-button' | dsBrowserOnly"
[disabled]="!form.valid"><i class="fas fa-sign-in-alt"></i> {{"login.form.submit" | translate}}</button>
</form>

View File

@@ -17,6 +17,7 @@ import { storeModuleConfig } from '../../../../app.reducer';
import { AuthMethod } from '../../../../core/auth/models/auth.method';
import { AuthMethodType } from '../../../../core/auth/models/auth.method-type';
import { HardRedirectService } from '../../../../core/services/hard-redirect.service';
import { BrowserOnlyMockPipe } from '../../../testing/browser-only-mock.pipe';
describe('LogInPasswordComponent', () => {
@@ -57,7 +58,8 @@ describe('LogInPasswordComponent', () => {
TranslateModule.forRoot()
],
declarations: [
LogInPasswordComponent
LogInPasswordComponent,
BrowserOnlyMockPipe,
],
providers: [
{ provide: AuthService, useClass: AuthServiceStub },

View File

@@ -2,5 +2,5 @@
<div *ngIf="(error | async)" class="alert alert-danger" role="alert" @fadeOut>{{ error | async }}</div>
<button class="btn btn-lg btn-primary btn-block mt-3" (click)="logOut()" data-test="logout-button"><i class="fas fa-sign-out-alt"></i> {{"logout.form.submit" | translate}}</button>
<button class="btn btn-lg btn-primary btn-block mt-3" (click)="logOut()" [attr.data-test]="'logout-button' | dsBrowserOnly"><i class="fas fa-sign-out-alt"></i> {{"logout.form.submit" | translate}}</button>
</div>

View File

@@ -12,6 +12,7 @@ import { Router } from '@angular/router';
import { AppState } from '../../app.reducer';
import { LogOutComponent } from './log-out.component';
import { RouterStub } from '../testing/router.stub';
import { BrowserOnlyMockPipe } from '../testing/browser-only-mock.pipe';
describe('LogOutComponent', () => {
@@ -46,7 +47,8 @@ describe('LogOutComponent', () => {
TranslateModule.forRoot()
],
declarations: [
LogOutComponent
LogOutComponent,
BrowserOnlyMockPipe,
],
providers: [
{ provide: Router, useValue: routerStub },

View File

@@ -18,7 +18,7 @@
>
<div class="card-columns row" *ngIf="objects?.hasSucceeded">
<div class="card-column col col-sm-6 col-lg-4" *ngFor="let column of (columns$ | async)" @fadeIn>
<div class="card-element" *ngFor="let object of column" data-test="grid-object">
<div class="card-element" *ngFor="let object of column" [attr.data-test]="'grid-object' | dsBrowserOnly">
<ds-listable-object-component-loader [object]="object" [viewMode]="viewMode" [context]="context" [linkType]="linkType"></ds-listable-object-component-loader>
</div>
</div>

View File

@@ -17,7 +17,7 @@
(next)="goNext()"
>
<ul *ngIf="objects?.hasSucceeded" class="list-unstyled" [ngClass]="{'ml-4': selectable}">
<li *ngFor="let object of objects?.payload?.page; let i = index; let last = last" class="mt-4 mb-4 d-flex" [class.border-bottom]="hasBorder && !last" data-test="list-object">
<li *ngFor="let object of objects?.payload?.page; let i = index; let last = last" class="mt-4 mb-4 d-flex" [class.border-bottom]="hasBorder && !last" [attr.data-test]="'list-object' | dsBrowserOnly">
<ds-selectable-list-item-control *ngIf="selectable" [index]="i"
[object]="object"
[selectionConfig]="selectionConfig"

View File

@@ -4,10 +4,10 @@
<div *ngIf="showScopeSelector === true" class="input-group-prepend">
<button class="scope-button btn btn-outline-secondary text-truncate" [ngbTooltip]="(selectedScope | async)?.name" type="button" (click)="openScopeModal()">{{(selectedScope | async)?.name || ('search.form.scope.all' | translate)}}</button>
</div>
<input type="text" [(ngModel)]="query" name="query" class="form-control" attr.aria-label="{{ searchPlaceholder }}" data-test="search-box"
<input type="text" [(ngModel)]="query" name="query" class="form-control" attr.aria-label="{{ searchPlaceholder }}" [attr.data-test]="'search-box' | dsBrowserOnly"
[placeholder]="searchPlaceholder">
<span class="input-group-append">
<button type="submit" class="search-button btn btn-{{brandColor}}" data-test="search-button"><i class="fas fa-search"></i> {{ ('search.form.search' | translate) }}</button>
<button type="submit" class="search-button btn btn-{{brandColor}}" [attr.data-test]="'search-button' | dsBrowserOnly"><i class="fas fa-search"></i> {{ ('search.form.search' | translate) }}</button>
</span>
</div>
</div>

View File

@@ -14,6 +14,7 @@ import { PaginationServiceStub } from '../testing/pagination-service.stub';
import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service';
import { createSuccessfulRemoteDataObject$ } from '../remote-data.utils';
import { FindListOptions } from '../../core/data/find-list-options.model';
import { BrowserOnlyMockPipe } from '../testing/browser-only-mock.pipe';
describe('SearchFormComponent', () => {
let comp: SearchFormComponent;
@@ -37,7 +38,10 @@ describe('SearchFormComponent', () => {
{ provide: SearchConfigurationService, useValue: searchConfigService },
{ provide: DSpaceObjectDataService, useValue: { findById: () => createSuccessfulRemoteDataObject$(undefined)} }
],
declarations: [SearchFormComponent]
declarations: [
SearchFormComponent,
BrowserOnlyMockPipe,
]
}).compileComponents();
}));

View File

@@ -4,6 +4,7 @@
class="filter-name d-flex" [attr.aria-controls]="regionId" [id]="toggleId"
[attr.aria-expanded]="false"
[attr.aria-label]="((collapsed$ | async) ? 'search.filters.filter.expand' : 'search.filters.filter.collapse') | translate"
[attr.data-test]="'filter-toggle' | dsBrowserOnly"
>
<h5 class="d-inline-block mb-0">
{{'search.filters.filter.' + filter.name + '.head'| translate}}

View File

@@ -13,6 +13,7 @@ import { FilterType } from '../../models/filter-type.model';
import { SearchConfigurationServiceStub } from '../../../testing/search-configuration-service.stub';
import { SEARCH_CONFIG_SERVICE } from '../../../../my-dspace-page/my-dspace-page.component';
import { SequenceService } from '../../../../core/shared/sequence.service';
import { BrowserOnlyMockPipe } from '../../../testing/browser-only-mock.pipe';
describe('SearchFilterComponent', () => {
let comp: SearchFilterComponent;
@@ -62,7 +63,10 @@ describe('SearchFilterComponent', () => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([]), NoopAnimationsModule],
declarations: [SearchFilterComponent],
declarations: [
SearchFilterComponent,
BrowserOnlyMockPipe,
],
providers: [
{ provide: SearchService, useValue: searchServiceStub },
{

View File

@@ -173,7 +173,7 @@ import { DsSelectComponent } from './ds-select/ds-select.component';
import { LogInOidcComponent } from './log-in/methods/oidc/log-in-oidc.component';
import { ThemedItemListPreviewComponent } from './object-list/my-dspace-result-list-element/item-list-preview/themed-item-list-preview.component';
import { ExternalLinkMenuItemComponent } from './menu/menu-item/external-link-menu-item.component';
import { BrowserOnlyPipe } from './utils/browser-only.pipe';
const MODULES = [
// Do NOT include UniversalModule, HttpModule, or JsonpModule here
CommonModule,
@@ -215,7 +215,8 @@ const PIPES = [
ObjectKeysPipe,
ObjectValuesPipe,
ConsolePipe,
ObjNgFor
ObjNgFor,
BrowserOnlyPipe,
];
const COMPONENTS = [

View File

@@ -1,5 +1,5 @@
<div class="facet-filter d-block mb-3 p-3">
<div (click)="toggle()" class="filter-name">
<div (click)="toggle()" class="filter-name" [attr.data-test]="'filter-toggle' | dsBrowserOnly">
<h5 class="d-inline-block mb-0">
{{ label | translate }}
</h5>

View File

@@ -0,0 +1,13 @@
import { Pipe, PipeTransform } from '@angular/core';
/**
* Support dsBrowserOnly in unit tests.
*/
@Pipe({
name: 'dsBrowserOnly'
})
export class BrowserOnlyMockPipe implements PipeTransform {
transform(value: string): string | undefined {
return value;
}
}

View File

@@ -5,6 +5,7 @@ import { SharedModule } from '../shared.module';
import { NgComponentOutletDirectiveStub } from './ng-component-outlet-directive.stub';
import { QueryParamsDirectiveStub } from './query-params-directive.stub';
import { RouterLinkDirectiveStub } from './router-link-directive.stub';
import { BrowserOnlyMockPipe } from './browser-only-mock.pipe';
/**
* This module isn't used. It serves to prevent the AoT compiler
@@ -21,7 +22,8 @@ import { RouterLinkDirectiveStub } from './router-link-directive.stub';
QueryParamsDirectiveStub,
MySimpleItemActionComponent,
RouterLinkDirectiveStub,
NgComponentOutletDirectiveStub
NgComponentOutletDirectiveStub,
BrowserOnlyMockPipe,
],
exports: [
QueryParamsDirectiveStub

View File

@@ -0,0 +1,24 @@
import { Inject, Pipe, PipeTransform, PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
/**
* A pipe that only returns its intput when run in the browser.
* Used to distinguish client-side rendered content from server-side rendered content.
*/
@Pipe({
name: 'dsBrowserOnly'
})
export class BrowserOnlyPipe implements PipeTransform {
constructor(
@Inject(PLATFORM_ID) private platformID: any,
) {
}
transform(value: string): string | undefined {
if (isPlatformBrowser((this.platformID))) {
return value;
} else {
return undefined;
}
}
}

View File

@@ -7,7 +7,7 @@
routerLinkActive="active"
[class.active]="currentMode === viewModeEnum.ListElement"
class="btn btn-secondary"
data-test="list-view">
[attr.data-test]="'list-view' | dsBrowserOnly">
<i class="fas fa-list" title="{{'search.view-switch.show-list' | translate}}"></i>
</a>
<a *ngIf="isToShow(viewModeEnum.GridElement)"
@@ -18,7 +18,7 @@
routerLinkActive="active"
[class.active]="currentMode === viewModeEnum.GridElement"
class="btn btn-secondary"
data-test="grid-view">
[attr.data-test]="'grid-view' | dsBrowserOnly">
<i class="fas fa-th-large" title="{{'search.view-switch.show-grid' | translate}}"></i>
</a>
<a *ngIf="isToShow(viewModeEnum.DetailedListElement)"
@@ -29,7 +29,7 @@
routerLinkActive="active"
[class.active]="currentMode === viewModeEnum.DetailedListElement"
class="btn btn-secondary"
data-test="detail-view">
[attr.data-test]="'detail-view' | dsBrowserOnly">
<i class="far fa-square" title="{{'search.view-switch.show-detail' | translate}}"></i>
</a>
</div>

View File

@@ -9,6 +9,7 @@ import { SearchService } from '../../core/shared/search/search.service';
import { ViewModeSwitchComponent } from './view-mode-switch.component';
import { SearchServiceStub } from '../testing/search-service.stub';
import { ViewMode } from '../../core/shared/view-mode.model';
import { BrowserOnlyMockPipe } from '../testing/browser-only-mock.pipe';
@Component({ template: '' })
class DummyComponent {
@@ -36,7 +37,8 @@ describe('ViewModeSwitchComponent', () => {
],
declarations: [
ViewModeSwitchComponent,
DummyComponent
DummyComponent,
BrowserOnlyMockPipe,
],
providers: [
{ provide: SearchService, useValue: searchService },

View File

@@ -3,6 +3,7 @@
<button *ngIf="(showDepositAndDiscard | async)"
type="button"
id="discard"
[attr.data-test]="'discard' | dsBrowserOnly"
class="btn btn-danger"
[disabled]="(processingSaveStatus | async) || (processingDepositStatus | async)"
(click)="$event.preventDefault();confirmDiscard(content)">
@@ -26,6 +27,7 @@
<button type="button"
class="btn btn-secondary"
id="save"
[attr.data-test]="'save' | dsBrowserOnly"
[disabled]="(processingSaveStatus | async) || !(hasUnsavedModification | async)"
(click)="save($event)">
<span><i class="fas fa-save"></i> {{'submission.general.save' | translate}}</span>
@@ -35,6 +37,7 @@
[class.btn-secondary]="(showDepositAndDiscard | async)"
class="btn"
id="saveForLater"
[attr.data-test]="'save-for-later' | dsBrowserOnly"
[disabled]="(processingSaveStatus | async) || (processingDepositStatus | async)"
(click)="saveLater($event)">
<span><i class="fas fa-save"></i> {{'submission.general.save-later' | translate}}</span>
@@ -42,6 +45,7 @@
<button *ngIf="(showDepositAndDiscard | async)"
type="button"
id="deposit"
[attr.data-test]="'deposit' | dsBrowserOnly"
class="btn btn-success"
[disabled]="(processingSaveStatus | async) || (processingDepositStatus | async)"
(click)="deposit($event)">

View File

@@ -15,12 +15,13 @@ import { SubmissionRestServiceStub } from '../../../shared/testing/submission-re
import { SubmissionFormFooterComponent } from './submission-form-footer.component';
import { SubmissionRestService } from '../../../core/submission/submission-rest.service';
import { createTestComponent } from '../../../shared/testing/utils.test';
import { BrowserOnlyMockPipe } from '../../../shared/testing/browser-only-mock.pipe';
const submissionServiceStub: SubmissionServiceStub = new SubmissionServiceStub();
const submissionId = mockSubmissionId;
describe('SubmissionFormFooterComponent Component', () => {
describe('SubmissionFormFooterComponent', () => {
let comp: SubmissionFormFooterComponent;
let compAsAny: any;
@@ -36,7 +37,8 @@ describe('SubmissionFormFooterComponent Component', () => {
],
declarations: [
SubmissionFormFooterComponent,
TestComponent
TestComponent,
BrowserOnlyMockPipe,
],
providers: [
{ provide: SubmissionService, useValue: submissionServiceStub },