perf: Improve render performance on the discover, movie and tv pages (#5084)

* perf(details):  Improve load performance for the TV and Movie Details pages

* perf(discover):  Improve load performance on the discover page

* fixed tests

* Fixed the dates

* test

* fix
snyk-upgrade-8fa6c2fd243bfece84b068e85447095d
Jamie 2 months ago committed by GitHub
parent 5cbb2ca528
commit 71c86a8db9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -14,7 +14,7 @@
<p id="detailed-request-requestedby-{{request.mediaId}}">{{'MediaDetails.RequestedBy' | translate}} {{request.username}}</p>
</div>
<div class="col-12">
<p id="detailed-request-date-{{request.mediaId}}">{{'MediaDetails.OnDate' | translate}} {{request.requestDate | dfnsFormat: 'Ppp'}}</p>
<p id="detailed-request-date-{{request.mediaId}}">{{'MediaDetails.OnDate' | translate}} {{request.requestDate | ombiDate: 'Ppp'}}</p>
</div>
<div class="col-12">
<p id="detailed-request-status-{{request.mediaId}}">{{'MediaDetails.Status' | translate}} <span class="badge badge-{{getClass(request)}}">{{getStatus(request) | translate}}</span></p>

@ -1,4 +1,3 @@
<p-skeleton id="cardLoading{{result.id}}" *ngIf="!fullyLoaded" width="100%" height="315px"></p-skeleton>
<div id="result{{result.id}}" *ngIf="fullyLoaded" class="ombi-card dark-card c" [style.display]="hide ? 'none' : 'block'">
<div class="card-top-info">
@ -43,8 +42,5 @@
</button>
</div>
</ng-template>
</div>
</div>
</div>

@ -1,7 +1,12 @@
<div class="small-middle-container">
<div class="section">
@defer (on viewport; prefetch on idle) {
<h2 id="genreHeading" data-toggle="collapse" href="#genreCollapse" role="button">{{ 'Discovery.Genres' | translate }}</h2>
<genre-button-select class="collapse show" id="genreCollapse"></genre-button-select>
}
@placeholder {
<p-skeleton width="100%" height="2rem"></p-skeleton>
}
</div>
<div class="section">
<h2>{{ 'Discovery.RecentlyRequestedTab' | translate }}</h2>

@ -3,6 +3,7 @@
<p-carousel #carousel [value]="requests" [numVisible]="3" [numScroll]="1"
[responsiveOptions]="responsiveOptions" [page]="0">
<ng-template let-result pTemplate="item">
@defer (on viewport; prefetch on idle) {
<ombi-detailed-card
[request]="result"
[isAdmin]="isAdmin"
@ -10,6 +11,10 @@
(onApprove)="approve(result)"
(onDeny)="deny(result)">
</ombi-detailed-card>
}
@placeholder {
<p-skeleton width="100%" height="315px"></p-skeleton>
}
</ng-template>
</p-carousel>
</div>

@ -2,7 +2,7 @@
<mat-card-header>
<mat-card-title>{{ issue.subject }}</mat-card-title>
<mat-card-subtitle>{{
'Issues.UserOnDate' | translate: { user: issue.userReported?.userName, date: issue.createdDate | dfnsFormat: 'PP' }
'Issues.UserOnDate' | translate: { user: issue.userReported?.userName, date: issue.createdDate | ombiDate: 'PP' }
}}</mat-card-subtitle>
<mat-card-subtitle>{{ issue.issueCategory.value }}</mat-card-subtitle>
</mat-card-header>

@ -82,7 +82,7 @@
(click)="deleteComment(comment.id)"
></i>
<p>{{ comment.comment }}</p>
<time>{{ comment.username }} • {{ comment.date | dfnsFormat: 'Ppp' }}</time>
<time>{{ comment.username }} • {{ comment.date | ombiDate: 'Ppp' }}</time>
</div>
</div>
</div>

@ -292,7 +292,12 @@
<div class="col-12">
<mat-card class="mat-elevation-z8 spacing-below">
<mat-card-content>
@defer (on viewport; prefetch on idle) {
{{ movie.overview }}
}
@placeholder {
<p-skeleton height="2rem" styleClass="mb-2"></p-skeleton>
}
</mat-card-content>
</mat-card>
</div>
@ -300,13 +305,23 @@
<div class="row">
<div class="col-12">
<cast-carousel [cast]="movie.credits.cast"></cast-carousel>
@defer (on viewport; prefetch on idle) {
<cast-carousel [cast]="movie.credits.cast"></cast-carousel>
}
@placeholder {
<p-skeleton height="2rem" styleClass="mb-2"></p-skeleton>
}
</div>
</div>
<div class="row">
<div class="col-12">
<crew-carousel [crew]="movie.credits.crew"></crew-carousel>
@defer (on viewport; prefetch on idle) {
<cast-carousel [cast]="movie.credits.crew"></cast-carousel>
}
@placeholder {
<p-skeleton height="2rem" styleClass="mb-2"></p-skeleton>
}
</div>
</div>
@ -320,6 +335,7 @@
<div class="row" *ngIf="movie.videos?.results?.length > 0">
<div class="col-12">
<mat-card class="mat-elevation-z8">
@defer (on viewport; prefetch on idle) {
<mat-card-header>{{ 'MediaDetails.Trailers' | translate }}</mat-card-header>
<mat-card-content>
<p-carousel class="no-indicator" [numVisible]="2" [numScroll]="10" [page]="0" [value]="movie.videos?.results">
@ -335,6 +351,10 @@
</ng-template>
</p-carousel>
</mat-card-content>
}
@placeholder {
<p-skeleton height="2rem" styleClass="mb-2"></p-skeleton>
}
</mat-card>
</div>
</div>
@ -345,6 +365,7 @@
<issues-panel [providerId]="movie.imdbId" [isAdmin]="isAdmin"></issues-panel>
</div>
@defer (on viewport; prefetch on idle) {
<mat-accordion class="mat-elevation-z8 spacing-below">
<mat-expansion-panel *ngIf="movie.recommendations?.results?.length > 0">
<mat-expansion-panel-header>
@ -398,6 +419,10 @@
</div>
</mat-expansion-panel>
</mat-accordion>
}
@placeholder {
<p-skeleton height="2rem" styleClass="mb-2"></p-skeleton>
}
</div>
</div>
</div>

@ -49,8 +49,8 @@
<div *ngIf="request">
<span class="label">{{ 'MediaDetails.RequestDate' | translate }}</span>
<span *ngIf="request.requestedDate < request.requestedDate4k"> {{ request.requestedDate4k | dfnsFormat: 'PP' }}</span>
<span *ngIf="request.requestedDate > request.requestedDate4k"> {{ request.requestedDate | dfnsFormat: 'PP' }}</span>
<span *ngIf="request.requestedDate < request.requestedDate4k"> {{ request.requestedDate4k | ombiDate: 'PP' }}</span>
<span *ngIf="request.requestedDate > request.requestedDate4k"> {{ request.requestedDate | ombiDate: 'PP' }}</span>
</div>
<div *ngIf="request && request.source !== RequestSource.Ombi">
@ -90,11 +90,11 @@
<hr />
<span class="label">{{ 'MediaDetails.TheatricalRelease' | translate }}</span>
{{ movie.releaseDate | dfnsFormat: 'PP' }}
{{ movie.releaseDate | ombiDate: 'PP' }}
<div *ngIf="movie.digitalReleaseDate">
<span class="label">{{ 'MediaDetails.DigitalRelease' | translate }}</span>
{{ movie.digitalReleaseDate | dfnsFormat: 'PP' }}
{{ movie.digitalReleaseDate | ombiDate: 'PP' }}
</div>
<div *ngIf="movie.voteCount">

@ -8,7 +8,7 @@
<div class="mobile-top-text">
<h1 id="mediaTitle" class="large-text">
{{ title }}
<span *ngIf="releaseDateFormat" class="grey-text"> ({{ releaseDate | dfnsFormat: 'P' }})</span>
<span *ngIf="releaseDateFormat" class="grey-text"> ({{ releaseDate | ombiDate: 'P' }})</span>
</h1>
<h2 class="tagline">{{ tagline }}</h2>

@ -31,7 +31,7 @@
<span id="status"> {{ tv.status | translateStatus }}</span>
</div>
<span class="label">{{ 'MediaDetails.FirstAired' | translate }}</span>
{{ tv.firstAired | dfnsFormat: 'PP' }}
{{ tv.firstAired | ombiDate: 'PP' }}
</div>
<div *ngIf="seasonCount">

@ -48,7 +48,7 @@
<ng-container matColumnDef="airDate">
<th mat-header-cell *matHeaderCellDef>{{ 'Requests.AirDate' | translate }}</th>
<td mat-cell *matCellDef="let element">{{ element.airDate | dfnsFormat: 'P' }}</td>
<td mat-cell *matCellDef="let element">{{ element.airDate | ombiDate: 'P' }}</td>
</ng-container>
<ng-container matColumnDef="status">

@ -10,7 +10,7 @@
| translate
: {
user: request.requestedUser.userAlias,
date: request.requestedDate | dfnsFormat: 'PP'
date: request.requestedDate | ombiDate: 'PP'
}
}}
<span *ngIf="request.denied"> - {{ request.deniedReason }}</span>
@ -35,7 +35,7 @@
<ng-container matColumnDef="airDate">
<th mat-header-cell *matHeaderCellDef>{{ 'Requests.AirDate' | translate }}</th>
<td mat-cell *matCellDef="let element">{{ element.airDate | dfnsFormat: 'P' }}</td>
<td mat-cell *matCellDef="let element">{{ element.airDate | ombiDate: 'P' }}</td>
</ng-container>
<ng-container matColumnDef="status">

@ -192,12 +192,10 @@
</div>
<div class="col-12 col-md-10">
@defer {
@defer (on viewport; prefetch on idle) {
<tv-request-grid id="requests-grid" [tvRequest]="tvRequest" [isAdmin]="isAdmin" [tv]="tv"></tv-request-grid>
} @placeholder {
<div class="loading-spinner">
<mat-spinner [color]="'accent'"></mat-spinner>
</div>
<p-skeleton height="2rem" styleClass="mb-2"></p-skeleton>
}
</div>
@ -216,14 +214,14 @@
</mat-panel-title>
</mat-expansion-panel-header>
@defer (on viewport) {
@defer (on viewport; prefetch on idle) {
<tv-requests-panel
[tvRequest]="tvRequest"
[isAdmin]="isAdmin"
[manageOwnRequests]="manageOwnRequests"
></tv-requests-panel>
} @placeholder {
<div class="loading-spinner">
<div class="loading-spinner" style="left: 50%;position: absolute;">
<mat-spinner [color]="'accent'"></mat-spinner>
</div>
}

@ -357,8 +357,13 @@
.media-row .btn-spacing{
margin-right:0;
}
.media-row span{
width:100%;
}
}
.placeholder {
height: 100px;
display: block;
}

@ -13,6 +13,7 @@ import { AuthGuard } from "../auth/auth.guard";
import { ArtistDetailsComponent } from "./components/artist/artist-details.component";
import { ReactiveFormsModule } from "@angular/forms";
import { ImageComponent } from "app/components";
import { SkeletonModule } from "primeng/skeleton";
const routes: Routes = [
@ -29,6 +30,7 @@ const routes: Routes = [
PipeModule,
CarouselModule,
ImageComponent,
SkeletonModule,
],
declarations: [
...fromComponents.components

@ -0,0 +1,17 @@
import { Pipe, PipeTransform } from "@angular/core";
import { FormatPipe } from 'ngx-date-fns';
@Pipe({
name: "ombiDate",
})
export class OmbiDatePipe implements PipeTransform {
constructor(
private FormatPipe: FormatPipe,
) {}
public transform(value: string, format: string ) {
const date = new Date(value);
return this.FormatPipe.transform(date, format);
}
}

@ -5,19 +5,19 @@
})
export class ThousandShortPipe implements PipeTransform {
transform(input: any, args?: any): any {
var exp, rounded,
var exp,
suffixes = ['k', 'M', 'G', 'T', 'P', 'E'];
if (Number.isNaN(input)) {
return null;
}
if (input < 1000) {
return input;
}
exp = Math.floor(Math.log(input) / Math.log(1000));
return (input / Math.pow(1000, exp)).toFixed(args) + suffixes[exp - 1];
}
}

@ -5,11 +5,14 @@ import { ThousandShortPipe } from './ThousandShortPipe';
import { SafePipe } from './SafePipe';
import { QualityPipe } from './QualityPipe';
import { OrderPipe } from './OrderPipe';
import { OmbiDatePipe } from './OmbiDatePipe';
import { FormatPipeModule, FormatPipe } from 'ngx-date-fns';
@NgModule({
imports: [],
declarations: [HumanizePipe, ThousandShortPipe, SafePipe, QualityPipe, TranslateStatusPipe, OrderPipe],
exports: [HumanizePipe, ThousandShortPipe, SafePipe, QualityPipe, TranslateStatusPipe, OrderPipe],
imports: [FormatPipeModule],
declarations: [HumanizePipe, ThousandShortPipe, SafePipe, QualityPipe, TranslateStatusPipe, OrderPipe, OmbiDatePipe],
exports: [HumanizePipe, ThousandShortPipe, SafePipe, QualityPipe, TranslateStatusPipe, OrderPipe, OmbiDatePipe],
providers: [FormatPipe],
})
export class PipeModule {
public static forRoot(): ModuleWithProviders<PipeModule> {

@ -85,7 +85,7 @@
</ng-container>
<ng-container matColumnDef="title">
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear>{{ 'Requests.AlbumName' | translate }}</th>
<td mat-cell *matCellDef="let element">{{ element.title }} ({{ element.releaseDate | dfnsFormat: 'P' }})</td>
<td mat-cell *matCellDef="let element">{{ element.title }} ({{ element.releaseDate | ombiDate: 'P' }})</td>
</ng-container>
<ng-container matColumnDef="requestedUser.requestedBy">
@ -95,7 +95,7 @@
<ng-container matColumnDef="requestedDate">
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear>{{ 'Requests.RequestDate' | translate }}</th>
<td mat-cell *matCellDef="let element">{{ element.requestedDate | dfnsFormat: 'PP' }}</td>
<td mat-cell *matCellDef="let element">{{ element.requestedDate | ombiDate: 'PP' }}</td>
</ng-container>
<ng-container matColumnDef="requestStatus">

@ -112,7 +112,7 @@
<ng-container matColumnDef="title">
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear>{{ 'Requests.RequestsTitle' | translate }}</th>
<td mat-cell id="title{{ element.id }}" *matCellDef="let element">{{ element.title }} ({{ element.releaseDate | dfnsFormat: 'P' }})</td>
<td mat-cell id="title{{ element.id }}" *matCellDef="let element">{{ element.title }} ({{ element.releaseDate | ombiDate: 'P' }})</td>
</ng-container>
<ng-container matColumnDef="requestedUser.requestedBy">
@ -124,7 +124,7 @@
<ng-container matColumnDef="requestedDate">
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear>{{ 'Requests.RequestDate' | translate }}</th>
<td mat-cell id="requestedDate{{ element.id }}" *matCellDef="let element">{{ getRequestDate(element) | dfnsFormat: 'PP' }}</td>
<td mat-cell id="requestedDate{{ element.id }}" *matCellDef="let element">{{ getRequestDate(element) | ombiDate: 'PP' }}</td>
</ng-container>
<ng-container matColumnDef="status">

@ -103,7 +103,7 @@
<ng-container matColumnDef="requestedDate">
<th mat-header-cell *matHeaderCellDef mat-sort-header disableClear>{{ 'Requests.RequestDate' | translate }}</th>
<td id="requestedDate{{ element.id }}" mat-cell *matCellDef="let element">
{{ element.requestedDate | dfnsFormat: 'PP' }}
{{ element.requestedDate | ombiDate: 'PP' }}
</td>
</ng-container>

@ -49,7 +49,7 @@
<div class="col-sm-5 small-padding">
<div>
<a href="http://www.imdb.com/title/{{ request.imdbId }}/" target="_blank">
<h4 class="request-title">{{ request.title }} ({{ request.releaseDate | dfnsFormat: 'P' }})</h4>
<h4 class="request-title">{{ request.title }} ({{ request.releaseDate | ombiDate: 'P' }})</h4>
</a>
</div>
<br />
@ -91,12 +91,12 @@
</div>
<div id="releaseDate">
{{ 'Requests.TheatricalRelease' | translate: { date: request.releaseDate | dfnsFormat: 'PP' } }}
{{ 'Requests.TheatricalRelease' | translate: { date: request.releaseDate | ombiDate: 'PP' } }}
</div>
<div *ngIf="request.digitalReleaseDate" id="digitalReleaseDate">
{{ 'Requests.DigitalRelease' | translate: { date: request.digitalReleaseDate | dfnsFormat: 'PP' } }}
{{ 'Requests.DigitalRelease' | translate: { date: request.digitalReleaseDate | ombiDate: 'PP' } }}
</div>
<div id="requestedDate">{{ 'Requests.RequestDate' | translate }} {{ request.requestedDate | dfnsFormat: 'PP' }}</div>
<div id="requestedDate">{{ 'Requests.RequestDate' | translate }} {{ request.requestedDate | ombiDate: 'PP' }}</div>
<br />
</div>
<div *ngIf="isAdmin">

@ -97,8 +97,8 @@
<i style="color: red" class="fas fa-check" pTooltip="{{ request.deniedReason }}"></i>
</div>
<div id="releaseDate">{{ 'Requests.ReleaseDate' | translate: { date: request.releaseDate | dfnsFormat: 'PP' } }}</div>
<div id="requestedDate">{{ 'Requests.RequestDate' | translate }} {{ request.requestedDate | dfnsFormat: 'PP' }}</div>
<div id="releaseDate">{{ 'Requests.ReleaseDate' | translate: { date: request.releaseDate | ombiDate: 'PP' } }}</div>
<div id="requestedDate">{{ 'Requests.RequestDate' | translate }} {{ request.requestedDate | ombiDate: 'PP' }}</div>
<br />
</div>
<!-- <div *ngIf="isAdmin">

@ -115,7 +115,7 @@
{{ ep.title }}
</td>
<td>
{{ ep.airDate | dfnsFormat: 'P' }}
{{ ep.airDate | ombiDate: 'P' }}
</td>
<td>
<span *ngIf="child.denied" class="label label-danger" id="deniedLabel" [translate]="'Common.Denied'">

@ -26,7 +26,7 @@
<div class="col-sm-5 small-padding">
<div>
<a href="http://www.imdb.com/title/{{ node.imdbId }}/" target="_blank">
<h4 class="request-title">{{ node.title }} ({{ node.releaseDate | dfnsFormat: 'P' }})</h4>
<h4 class="request-title">{{ node.title }} ({{ node.releaseDate | ombiDate: 'P' }})</h4>
</a>
</div>
<br />
@ -35,7 +35,7 @@
<span class="label label-success">{{ node.status }}</span>
</div>
<div>Release Date: {{ node.releaseDate | dfnsFormat: 'PP' }}</div>
<div>Release Date: {{ node.releaseDate | ombiDate: 'PP' }}</div>
<div *ngIf="isAdmin">
<div *ngIf="node.qualityOverrideTitle" class="quality-override">
{{ 'Requests.QualityOverride' | translate }}

@ -13,7 +13,7 @@
</div>
</div>
<small>Updated at {{ data.updateDate | dfnsFormat: 'PP' }}</small>
<small>Updated at {{ data.updateDate | ombiDate: 'PP' }}</small>
</mat-dialog-content>
<div mat-dialog-actions class="right-buttons">

@ -16,7 +16,7 @@
<p class="name" *ngIf="m?.username">{{ m.username }}</p>
<br />
<p class="message">{{ m.message }}</p>
<p class="timestamp">{{ m.date | dfnsFormat: 'Ppp' }}</p>
<p class="timestamp">{{ m.date | ombiDate: 'Ppp' }}</p>
</div>
</div>
</div>

@ -73,7 +73,7 @@
{{ ep.title }}
</div>
<div class="col-2" *ngIf="ep.airDateDisplay != 'Unknown'">
{{ ep.airDate | dfnsFormat: 'P' }}
{{ ep.airDate | ombiDate: 'P' }}
</div>
<div class="col-2" *ngIf="ep.airDateDisplay == 'Unknown'">
{{ ep.airDateDisplay }}

@ -70,13 +70,13 @@
<th mat-header-cell *matHeaderCellDef>Next Request Due</th>
<td mat-cell *matCellDef="let u">
<div *ngIf="u.movieRequestQuota != null && u.movieRequestQuota.remaining != u.movieRequestLimit">
{{ 'UserManagment.MovieDue' | translate: { date: (u.movieRequestQuota.nextRequest | dfnsFormat: 'P') } }}
{{ 'UserManagment.MovieDue' | translate: { date: (u.movieRequestQuota.nextRequest | ombiDate: 'P') } }}
</div>
<div *ngIf="u.episodeRequestQuota != null && u.episodeRequestQuota.remaining != u.episodeRequestLimit">
{{ 'UserManagment.TvDue' | translate: { date: (u.episodeRequestQuota.nextRequest | dfnsFormat: 'P') } }}
{{ 'UserManagment.TvDue' | translate: { date: (u.episodeRequestQuota.nextRequest | ombiDate: 'P') } }}
</div>
<div *ngIf="u.musicRequestQuota != null && u.musicRequestQuota.remaining != u.musicRequestLimit">
{{ 'UserManagment.MusicDue' | translate: { date: (u.musicRequestQuota.nextRequest | dfnsFormat: 'P') } }}
{{ 'UserManagment.MusicDue' | translate: { date: (u.musicRequestQuota.nextRequest | ombiDate: 'P') } }}
</div>
</td>
</ng-container>
@ -84,7 +84,7 @@
<th mat-header-cell *matHeaderCellDef mat-sort-header>Last Logged In</th>
<td mat-cell *matCellDef="let u">
<span *ngIf="u.lastLoggedIn">
{{ u.lastLoggedIn | dfnsFormat: 'Ppp' }}
{{ u.lastLoggedIn | ombiDate: 'Ppp' }}
</span>
<span *ngIf="!u.lastLoggedIn"> Not logged in yet! </span>
</td>

@ -1,163 +1,162 @@
import { movieDetailsPage as Page } from "@/integration/page-objects";
import { movieDetailsPage as Page } from '@/integration/page-objects';
describe("Movie Details Buttons", () => {
it("Movie Requested by Admin should be auto approved", () => {
cy.login();
describe('Movie Details Buttons', () => {
it('Movie Requested by Admin should be auto approved', () => {
cy.login();
Page.visit("587807");
Page.requestButton.click();
Page.adminOptionsDialog.isOpen();
Page.visit('587807');
Page.requestButton.click();
Page.adminOptionsDialog.isOpen();
Page.adminOptionsDialog.requestButton.click();
Page.adminOptionsDialog.requestButton.click();
cy.verifyNotification("Request for Tom & Jerry has been added successfully");
cy.verifyNotification('Request for Tom & Jerry has been added successfully');
Page.requestedButton.should("be.visible");
});
Page.requestedButton.should('be.visible');
});
it("Movie Requested by Regular user should be pending", () => {
cy.generateUniqueId().then((id) => {
cy.login();
const roles = [];
roles.push({ value: "RequestMovie", enabled: true });
cy.createUser(id, "a", roles).then(() => {
cy.loginWithCreds(id, "a");
it('Movie Requested by Regular user should be pending', () => {
cy.generateUniqueId().then((id) => {
cy.login();
const roles = [];
roles.push({ value: 'RequestMovie', enabled: true });
cy.createUser(id, 'a', roles).then(() => {
cy.loginWithCreds(id, 'a');
Page.visit("651571");
Page.visit('651571');
Page.requestButton.click();
cy.verifyNotification("Request for Breach has been added successfully");
Page.requestButton.click();
cy.verifyNotification('Request for Breach has been added successfully');
Page.requestedButton.should("be.visible");
});
});
});
Page.requestedButton.should('be.visible');
});
});
});
it("Movie Requested by Regular with no movie permission", () => {
cy.generateUniqueId().then((id) => {
cy.login();
const roles = [];
roles.push({ value: "RequestTv", enabled: true });
cy.createUser(id, "a", roles).then(() => {
cy.loginWithCreds(id, "a");
it('Movie Requested by Regular with no movie permission', () => {
cy.generateUniqueId().then((id) => {
cy.login();
const roles = [];
roles.push({ value: 'RequestTv', enabled: true });
cy.createUser(id, 'a', roles).then(() => {
cy.loginWithCreds(id, 'a');
Page.visit("791373");
Page.visit('791373');
Page.requestButton.click();
cy.verifyNotification("You do not have permissions to Request a Movie");
Page.requestButton.click();
cy.verifyNotification('You do not have permissions to Request a Movie');
Page.requestedButton.should("not.exist");
});
});
});
Page.requestedButton.should('not.exist');
});
});
});
it("Movie Requested by Regular can be approved by admin", () => {
cy.generateUniqueId().then((id) => {
cy.login();
const roles = [];
roles.push({ value: "RequestMovie", enabled: true });
cy.createUser(id, "a", roles).then(() => {
cy.loginWithCreds(id, "a");
it('Movie Requested by Regular can be approved by admin', () => {
cy.generateUniqueId().then((id) => {
cy.login();
const roles = [];
roles.push({ value: 'RequestMovie', enabled: true });
cy.createUser(id, 'a', roles).then(() => {
cy.loginWithCreds(id, 'a');
Page.visit("793723");
Page.visit('793723');
Page.requestButton.click();
cy.verifyNotification("Request for Sentinelle has been added successfully");
Page.requestButton.click();
cy.verifyNotification('Request for Sentinelle has been added successfully');
Page.requestedButton.should("be.visible");
Page.requestedButton.should('be.visible');
// Login as admin now
cy.removeLogin();
cy.login();
cy.reload();
// Login as admin now
cy.removeLogin();
cy.login();
cy.reload();
Page.visit("793723");
cy.intercept('GET', '**/Request/movie/info/**').as('requestCall');
Page.approveButton.should("exist");
Page.approveButton.click();
Page.visit('793723');
cy.verifyNotification("Successfully Approved");
});
});
});
cy.wait('@requestCall').then((__) => {
Page.approveButton.should('exist');
Page.approveButton.click();
it("Movie Requested, mark as available", () => {
cy.login();
cy.verifyNotification('Successfully Approved');
});
});
});
});
Page.visit("12444");
it('Movie Requested, mark as available', () => {
cy.login();
Page.requestButton.click();
Page.adminOptionsDialog.isOpen();
Page.adminOptionsDialog.requestButton.click();
cy.verifyNotification(
"Request for Harry Potter and the Deathly Hallows: Part 1 has been added successfully"
);
Page.visit('12444');
cy.reload();
Page.requestButton.click();
Page.adminOptionsDialog.isOpen();
Page.adminOptionsDialog.requestButton.click();
cy.verifyNotification('Request for Harry Potter and the Deathly Hallows: Part 1 has been added successfully');
Page.markAvailableButton.should("exist");
Page.markAvailableButton.click();
cy.intercept('GET', '**/Images/banner/movie/**').as('bannerLoad');
cy.reload();
cy.waitUntil(() => {
return Page.availableButton.should("be.visible");
})
cy.wait('@bannerLoad').then((__) => {
Page.markAvailableButton.should('exist');
Page.markAvailableButton.click();
cy.verifyNotification("Request is now available");
Page.availableButton.should("exist");
});
cy.verifyNotification('Request is now available');
Page.availableButton.should('exist');
});
});
it.skip("Movie Requested, Deny Movie", () => {
cy.login();
it.skip('Movie Requested, Deny Movie', () => {
cy.login();
Page.visit("671");
Page.visit('671');
Page.requestButton.click();
Page.adminOptionsDialog.isOpen();
Page.adminOptionsDialog.requestButton.click();
cy.verifyNotification(
"Request for Harry Potter and the Philosopher's Stone has been added successfully"
);
Page.requestButton.click();
Page.adminOptionsDialog.isOpen();
Page.adminOptionsDialog.requestButton.click();
cy.verifyNotification("Request for Harry Potter and the Philosopher's Stone has been added successfully");
cy.reload();
cy.reload();
Page.denyButton.should("exist");
Page.denyButton.click();
Page.denyButton.should('exist');
Page.denyButton.click();
Page.denyModal.denyReason.type("Automation Tests");
cy.wait(500);
Page.denyModal.denyButton.click();
Page.denyModal.denyReason.type('Automation Tests');
cy.wait(500);
Page.denyModal.denyButton.click();
Page.deniedButton.should('exist');
Page.deniedButton.should('exist');
cy.verifyNotification("Denied Request");
cy.verifyNotification('Denied Request');
cy.wait(1000);
Page.informationPanel.denyReason.should('have.text', "Automation Tests");
});
cy.wait(1000);
Page.informationPanel.denyReason.should('have.text', 'Automation Tests');
});
it("Movie View Collection should be available", () => {
cy.login();
it('Movie View Collection should be available', () => {
cy.login();
Page.visit("671");
Page.visit('671');
Page.viewCollectionButton.should('be.visible');
});
Page.viewCollectionButton.should('be.visible');
});
it("Non requested movie valid buttons", () => {
cy.login();
it('Non requested movie valid buttons', () => {
cy.login();
Page.visit("590706");
Page.visit('590706');
Page.viewCollectionButton.should('not.exist');
Page.approveButton.should('not.exist');
Page.denyButton.should('not.exist');
Page.deniedButton.should('not.exist');
Page.markAvailableButton.should('not.exist');
Page.viewOnEmbyButton.should('not.exist');
Page.viewOnJellyfinButton.should('not.exist');
Page.viewOnPlexButton.should('not.exist');
Page.requestedButton.should('not.exist');
Page.reportIssueButton.should('not.exist'); // Issuess not enabled
Page.requestButton.should('exist');
});
Page.viewCollectionButton.should('not.exist');
Page.approveButton.should('not.exist');
Page.denyButton.should('not.exist');
Page.deniedButton.should('not.exist');
Page.markAvailableButton.should('not.exist');
Page.viewOnEmbyButton.should('not.exist');
Page.viewOnJellyfinButton.should('not.exist');
Page.viewOnPlexButton.should('not.exist');
Page.requestedButton.should('not.exist');
Page.reportIssueButton.should('not.exist'); // Issuess not enabled
Page.requestButton.should('exist');
});
});

Loading…
Cancel
Save