This is the codeAbility Sharing Platform! Learn more about the codeAbility Sharing Platform.

Skip to content
Snippets Groups Projects
Commit 91d5652b authored by Michael Breu's avatar Michael Breu :speech_balloon:
Browse files

Draft: Resolve "GitLab Broadcast messages werden in GitSearch nicht mehr angezeigt?"

parent 5aee09e2
Branches
2 merge requests!235Bringing some minor issues and bug fixes to production,!232Resolve "GitLab Broadcast messages werden in GitSearch nicht mehr angezeigt?"
Showing
with 91 additions and 72 deletions
......@@ -5,14 +5,19 @@
"version": "0.2.0",
"configurations": [
{
"name": "Launch jest explicitly",
"program": "${workspaceFolder}/node_modules/jest/bin/jest.js",
"type": "node",
"request": "launch",
"args": ["--verbose", "--config", "jest.conf.js"],
"skipFiles": [
"<node_internals>/**"
"name": "Jest Current File",
"program": "${workspaceFolder}/node_modules/@angular/cli/bin/ng",
"cwd": "${workspaceFolder}",
"args": [
"test",
"--testMatch=\"**/+(*.)+(spec|test).+(ts|js)?(x)\"",
"--testPathPattern=${fileBasenameNoExtension}",
"--run-in-band",
],
"type": "node"
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
},
{
"type": "node",
......@@ -26,7 +31,6 @@
"<node_internals>/**"
],
},
{
"type": "node",
"name": "ng test",
......
......@@ -38,6 +38,7 @@
"jspdf": "^2.5.1",
"lodash": "^4.17.21",
"moment": "^2.29.4",
"ng-http-caching": "^13.0.10",
"ngx-cookie-service": "^13.1.2",
"ngx-infinite-scroll": "10.0.1",
"ngx-markdown": "^13.1.0",
......@@ -25897,6 +25898,18 @@
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
"dev": true
},
"node_modules/ng-http-caching": {
"version": "13.0.10",
"resolved": "https://registry.npmjs.org/ng-http-caching/-/ng-http-caching-13.0.10.tgz",
"integrity": "sha512-xYu6cup/byJZx9AksGlMH9wMOLRYmKtvslRNlighChJXU5brHz1CMPpQ+A2AqAXRGQbFZrpYcINgjwx9FmztNw==",
"dependencies": {
"tslib": "^2.3.0"
},
"peerDependencies": {
"@angular/common": "^13.0.0",
"@angular/core": "^13.0.0"
}
},
"node_modules/ngx-cookie-service": {
"version": "13.2.1",
"resolved": "https://registry.npmjs.org/ngx-cookie-service/-/ngx-cookie-service-13.2.1.tgz",
......@@ -114,6 +114,7 @@
"jspdf": "^2.5.1",
"lodash": "^4.17.21",
"moment": "^2.29.4",
"ng-http-caching": "^13.0.10",
"ngx-cookie-service": "^13.1.2",
"ngx-infinite-scroll": "10.0.1",
"ngx-markdown": "^13.1.0",
......
......@@ -8,6 +8,7 @@ import { FaIconLibrary, FontAwesomeModule } from '@fortawesome/angular-fontaweso
import { NgxWebstorageModule } from 'ngx-webstorage';
import dayjs from 'dayjs/esm';
import { NgbDateAdapter, NgbDatepickerConfig } from '@ng-bootstrap/ng-bootstrap';
import { NgHttpCachingModule, NgHttpCachingConfig, NgHttpCachingStrategy } from 'ng-http-caching';
import { ApplicationConfigService } from 'app/core/config/application-config.service';
import './config/dayjs';
......@@ -44,6 +45,13 @@ import { IndexManagementComponent } from './admin/index-management/index-managem
export let AppInjector: Injector;
const ngHttpCachingConfig: NgHttpCachingConfig = {
// see https://github.com/nigrosimone/ng-http-caching
lifetime: 1000 * 60 * 10, // cache expire after 600 seconds,
allowedMethod: ['GET', 'HEAD'],
cacheStrategy: NgHttpCachingStrategy.DISALLOW_ALL, // cache only requests with special caching header
};
@NgModule({
imports: [
BrowserModule,
......@@ -60,6 +68,7 @@ export let AppInjector: Injector;
FontAwesomeModule,
BrowserAnimationsModule,
HttpClientModule,
NgHttpCachingModule.forRoot(ngHttpCachingConfig),
],
providers: [
Title,
......
......@@ -6,10 +6,9 @@
<router-outlet name="navbar"></router-outlet>
</div>
</div>
<div class="row" *ngFor="let m of getActiveMessages()">
<div class="alert alert-warning text-center debugging" style="width: 100%">{{ m.message }}</div>
<div class="pad" *ngIf="getActiveMessages()">
<div *ngFor="let m of getActiveMessages()" class="alert alert-warning text-center" style="width: 100%">{{ m.message }}</div>
</div>
<div class="pad"></div>
<!-- Main content -->
<router-outlet></router-outlet>
......
// .pagewrapper {
// max-width: 1920px;
// margin-left: auto;
// margin-right: auto;
// margin-top: 20px;
// box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
// }
.pad {
padding-top: 80px;
}
......
......@@ -17,6 +17,8 @@ import { MessageService, BroadCastMessage } from 'app/shared/service/message-ser
export class MainComponent implements OnInit {
private renderer: Renderer2;
activeMessages: Array<BroadCastMessage> = [];
constructor(
private accountService: AccountService,
private titleService: Title,
......@@ -64,7 +66,8 @@ export class MainComponent implements OnInit {
}
public getActiveMessages(): Array<BroadCastMessage> {
return this.messageService.getActiveMessages(); //
this.messageService.getActiveMessages().subscribe(messages => (this.activeMessages = messages));
return this.activeMessages;
}
private getPageTitle(routeSnapshot: ActivatedRouteSnapshot): string {
......
......@@ -2,6 +2,8 @@ import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { ApplicationConfigService } from 'app/core/config/application-config.service';
import { map, Observable } from 'rxjs';
import { NgHttpCachingHeaders } from 'ng-http-caching';
export interface BroadCastMessage {
message: string;
......@@ -26,38 +28,29 @@ export class MessageService {
public messageResourceURL = this.applicationConfigService.getEndpointFor('api/applicationInfo/broadcastMessages');
private messages = new Array<BroadCastMessage>();
private nextUpdate = 0;
constructor(protected http: HttpClient, private applicationConfigService: ApplicationConfigService) {}
public getActiveMessages(): Array<BroadCastMessage> {
public getActiveMessages(): Observable<BroadCastMessage[]> {
const now = new Date();
return this.getMessages().filter(m => m.starts_at <= now && m.ends_at >= now); //
return this.getMessages().pipe(map(messages => messages.filter(m => m.starts_at <= now && m.ends_at >= now)));
}
public getMessages(): Array<BroadCastMessage> {
const now = new Date().getTime();
if (this.nextUpdate > now) {
return this.messages;
}
this.nextUpdate = now + 60 * 1000; // wait at least 1 Minute for next try
const resp = this.http.get<Array<BroadCastMessage>>(this.messageResourceURL);
resp.subscribe(response => {
// first convert dates correctly :-(
response.forEach(m => {
m.starts_at = new Date(m.starts_at);
m.ends_at = new Date(m.ends_at);
});
// Data will be cached
this.messages = response;
this.nextUpdate = new Date().getTime() + 10 * 60 * 1000; // wait 10 Minute for next try
return response;
});
return this.messages;
public getMessages(): Observable<BroadCastMessage[]> {
return this.http
.get<Array<BroadCastMessage>>(this.messageResourceURL, {
headers: {
[NgHttpCachingHeaders.ALLOW_CACHE]: '1',
},
})
.pipe(
map(messages => {
messages.forEach(m => {
m.starts_at = new Date(m.starts_at);
m.ends_at = new Date(m.ends_at);
});
return messages;
})
);
}
}
......@@ -5,6 +5,10 @@ import at.ac.uibk.gitsearch.service.dto.BroadCastMessageDTO;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import java.io.IOException;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
import java.util.stream.Collectors;
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.junit.Assert;
......@@ -13,13 +17,13 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest(classes = GitsearchApp.class)
public class MessageServiceIT {
class MessageServiceIT {
@Autowired
MessageService messageService;
@Test
public void loadMessages() throws JsonParseException, JsonMappingException, IOException {
void loadMessages() throws JsonParseException, JsonMappingException, IOException {
BroadCastMessageDTO[] messages = messageService.getMessages();
if (messages == null) {
// give it more time (or trigger reload)
......@@ -28,6 +32,13 @@ public class MessageServiceIT {
}
Assert.assertNotNull("This may fail, due to timing problems", messages);
MatcherAssert.assertThat("This may fail, if there are no messages in gitlab", messages, Matchers.arrayWithSize(2));
Calendar end2023 = Calendar.getInstance();
end2023.set(2024, 0, 1, 0, 0, 0);
List<BroadCastMessageDTO> preparedTestMessages = Arrays
.stream(messages)
.filter(m -> m.getEnds_at().before(end2023.getTime()))
.collect(Collectors.toList());
MatcherAssert.assertThat("This may fail, if there are no old messages in gitlab", preparedTestMessages, Matchers.hasSize(2));
}
}
......@@ -3,8 +3,6 @@ import { NavBarPage, SignInPage } from '../../page-objects/jhi-page-objects';
import { LikesComponentsPage, LikesUpdatePage } from './likes.page-object';
const expect = chai.expect;
describe('Likes e2e test', () => {
let navBarPage: NavBarPage;
let signInPage: SignInPage;
......@@ -13,7 +11,7 @@ describe('Likes e2e test', () => {
const username = process.env.E2E_USERNAME ?? 'admin';
const password = process.env.E2E_PASSWORD ?? 'search@admin';
before(async () => {
beforeEach(async () => {
browser.get('/login');
await browser.sleep(2000);
navBarPage = new NavBarPage();
......@@ -27,18 +25,18 @@ describe('Likes e2e test', () => {
await navBarPage.goToEntity('likes');
likesComponentsPage = new LikesComponentsPage();
await browser.wait(ec.visibilityOf(likesComponentsPage.title), 5000);
expect(await likesComponentsPage.getTitle()).to.eq('gitsearchApp.likes.home.title');
expect(await likesComponentsPage.getTitle()).toEqual('gitsearchApp.likes.home.title');
await browser.wait(ec.or(ec.visibilityOf(likesComponentsPage.entities), ec.visibilityOf(likesComponentsPage.noResult)), 10000);
});
it('should load create Likes page', async () => {
await likesComponentsPage.clickOnCreateButton();
likesUpdatePage = new LikesUpdatePage();
expect(await likesUpdatePage.getPageTitle()).to.eq('gitsearchApp.likes.home.createOrEditLabel');
expect(await likesUpdatePage.getPageTitle()).toEqual('gitsearchApp.likes.home.createOrEditLabel');
await likesUpdatePage.cancel();
});
after(async () => {
afterEach(async () => {
await navBarPage.autoSignOut();
});
});
......@@ -7,8 +7,6 @@ import {
SavedSearchesUpdatePage,
} from './saved-searches.page-object';
const expect = chai.expect;
describe('SavedSearches e2e test', () => {
let navBarPage: NavBarPage;
let signInPage: SignInPage;
......@@ -17,7 +15,7 @@ describe('SavedSearches e2e test', () => {
const username = process.env.E2E_USERNAME ?? 'admin';
const password = process.env.E2E_PASSWORD ?? 'search@admin';
before(async () => {
beforeEach(async () => {
browser.get('/login');
await browser.sleep(2000);
navBarPage = new NavBarPage();
......@@ -31,7 +29,7 @@ describe('SavedSearches e2e test', () => {
await navBarPage.goToEntity('saved-searches');
savedSearchesComponentsPage = new SavedSearchesComponentsPage();
await browser.wait(ec.visibilityOf(savedSearchesComponentsPage.title), 5000);
expect(await savedSearchesComponentsPage.getTitle()).to.eq('gitsearchApp.savedSearches.home.title');
expect(await savedSearchesComponentsPage.getTitle()).toEqual('gitsearchApp.savedSearches.home.title');
await browser.wait(
ec.or(ec.visibilityOf(savedSearchesComponentsPage.entities), ec.visibilityOf(savedSearchesComponentsPage.noResult)),
10000
......@@ -41,11 +39,11 @@ describe('SavedSearches e2e test', () => {
it('should load create SavedSearches page', async () => {
await savedSearchesComponentsPage.clickOnCreateButton();
savedSearchesUpdatePage = new SavedSearchesUpdatePage();
expect(await savedSearchesUpdatePage.getPageTitle()).to.eq('gitsearchApp.savedSearches.home.createOrEditLabel');
expect(await savedSearchesUpdatePage.getPageTitle()).toEqual('gitsearchApp.savedSearches.home.createOrEditLabel');
await savedSearchesUpdatePage.cancel();
});
after(async () => {
afterEach(async () => {
await navBarPage.autoSignOut();
});
});
......@@ -7,8 +7,6 @@ import {
UserWatchListUpdatePage,
} from './user-watch-list.page-object';
const expect = chai.expect;
describe('UserWatchList e2e test', () => {
let navBarPage: NavBarPage;
let signInPage: SignInPage;
......@@ -17,7 +15,7 @@ describe('UserWatchList e2e test', () => {
const username = process.env.E2E_USERNAME ?? 'admin';
const password = process.env.E2E_PASSWORD ?? 'search@admin';
before(async () => {
beforeEach(async () => {
browser.get('/login');
await browser.sleep(2000);
navBarPage = new NavBarPage();
......@@ -30,7 +28,7 @@ describe('UserWatchList e2e test', () => {
await navBarPage.goToEntity('user-watch-list');
userWatchListComponentsPage = new UserWatchListComponentsPage();
await browser.wait(ec.visibilityOf(userWatchListComponentsPage.title), 5000);
expect(await userWatchListComponentsPage.getTitle()).to.eq('gitsearchApp.userWatchList.home.title');
expect(await userWatchListComponentsPage.getTitle()).toEqual('gitsearchApp.userWatchList.home.title');
await browser.wait(
ec.or(ec.visibilityOf(userWatchListComponentsPage.entities), ec.visibilityOf(userWatchListComponentsPage.noResult)),
10000
......@@ -40,11 +38,13 @@ describe('UserWatchList e2e test', () => {
it('should load create UserWatchList page', async () => {
await userWatchListComponentsPage.clickOnCreateButton();
userWatchListUpdatePage = new UserWatchListUpdatePage();
expect(await userWatchListUpdatePage.getPageTitle()).to.eq('gitsearchApp.userWatchList.home.createOrEditLabel');
expect(await userWatchListUpdatePage.getPageTitle()).toEqual('gitsearchApp.userWatchList.home.createOrEditLabel');
await userWatchListUpdatePage.cancel();
});
after(async () => {
afterEach(async () => {
if(navBarPage) {
await navBarPage.autoSignOut();
}
});
});
......@@ -3,15 +3,13 @@ import { browser, element, by, ExpectedConditions as ec } from 'protractor';
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { NavBarPage, SignInPage } from '../page-objects/jhi-page-objects';
const expect = chai.expect;
describe('search', () => {
let navBarPage: NavBarPage;
let signInPage: SignInPage;
const username = process.env.E2E_USERNAME || 'admin';
const password = process.env.E2E_PASSWORD || 'search@admin';
before(async () => {
beforeEach(async () => {
browser.get('/login');
await browser.sleep(2000);
navBarPage = new NavBarPage(true);
......@@ -24,14 +22,14 @@ describe('search', () => {
const expect2 = 'home.logged.message';
await browser.wait(ec.visibilityOf(element(by.id('home-logged-message'))));
const value2 = await element(by.id('home-logged-message')).getAttribute('jhiTranslate');
expect(value2).to.eq(expect2);
expect(value2).toEqual(expect2);
await navBarPage.clickOnSearch();
await browser.sleep(3000);
await browser.wait(ec.visibilityOf(element(by.id('numberOfResults'))), 10000);
});
after(async () => {
afterEach(async () => {
await navBarPage.autoSignOut();
});
});
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment