Skip to content

Commit 8bc2c87

Browse files
committed
Merge branch 'dspace-7_x' into 4099-duplicate-view-events_contibute-7.x
2 parents 9a0e4ec + 3a04ea8 commit 8bc2c87

18 files changed

Lines changed: 505 additions & 196 deletions

.eslintrc.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,10 +231,13 @@
231231
"*.json5"
232232
],
233233
"extends": [
234-
"plugin:jsonc/recommended-with-jsonc"
234+
"plugin:jsonc/recommended-with-json5"
235235
],
236236
"rules": {
237-
"no-irregular-whitespace": "error",
237+
// The ESLint core no-irregular-whitespace rule doesn't work well in JSON
238+
// See: https://ota-meshi.github.io/eslint-plugin-jsonc/rules/no-irregular-whitespace.html
239+
"no-irregular-whitespace": "off",
240+
"jsonc/no-irregular-whitespace": "error",
238241
"no-trailing-spaces": "error",
239242
"jsonc/comma-dangle": [
240243
"error",

.github/workflows/build.yml

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,12 +184,84 @@ jobs:
184184
# Get homepage and verify that the <meta name="title"> tag includes "DSpace".
185185
# If it does, then SSR is working, as this tag is created by our MetadataService.
186186
# This step also prints entire HTML of homepage for easier debugging if grep fails.
187-
- name: Verify SSR (server-side rendering)
187+
- name: Verify SSR (server-side rendering) on Homepage
188188
run: |
189189
result=$(wget -O- -q http://127.0.0.1:4000/home)
190190
echo "$result"
191191
echo "$result" | grep -oE "<meta name=\"title\" [^>]*>" | grep DSpace
192192
193+
# Get a specific community in our test data and verify that the "<h1>" tag includes "Publications" (the community name).
194+
# If it does, then SSR is working.
195+
- name: Verify SSR on a Community page
196+
run: |
197+
result=$(wget -O- -q http://127.0.0.1:4000/communities/0958c910-2037-42a9-81c7-dca80e3892b4)
198+
echo "$result"
199+
echo "$result" | grep -oE "<h1 [^>]*>[^><]*</h1>" | grep Publications
200+
201+
# Get a specific collection in our test data and verify that the "<h1>" tag includes "Articles" (the collection name).
202+
# If it does, then SSR is working.
203+
- name: Verify SSR on a Collection page
204+
run: |
205+
result=$(wget -O- -q http://127.0.0.1:4000/collections/282164f5-d325-4740-8dd1-fa4d6d3e7200)
206+
echo "$result"
207+
echo "$result" | grep -oE "<h1 [^>]*>[^><]*</h1>" | grep Articles
208+
209+
# Get a specific publication in our test data and verify that the <meta name="title"> tag includes
210+
# the title of this publication. If it does, then SSR is working.
211+
- name: Verify SSR on a Publication page
212+
run: |
213+
result=$(wget -O- -q http://127.0.0.1:4000/entities/publication/6160810f-1e53-40db-81ef-f6621a727398)
214+
echo "$result"
215+
echo "$result" | grep -oE "<meta name=\"title\" [^>]*>" | grep "An Economic Model of Mortality Salience"
216+
217+
# Get a specific person in our test data and verify that the <meta name="title"> tag includes
218+
# the name of the person. If it does, then SSR is working.
219+
- name: Verify SSR on a Person page
220+
run: |
221+
result=$(wget -O- -q http://127.0.0.1:4000/entities/person/b1b2c768-bda1-448a-a073-fc541e8b24d9)
222+
echo "$result"
223+
echo "$result" | grep -oE "<meta name=\"title\" [^>]*>" | grep "Simmons, Cameron"
224+
225+
# Get a specific project in our test data and verify that the <meta name="title"> tag includes
226+
# the name of the project. If it does, then SSR is working.
227+
- name: Verify SSR on a Project page
228+
run: |
229+
result=$(wget -O- -q http://127.0.0.1:4000/entities/project/46ccb608-a74c-4bf6-bc7a-e29cc7defea9)
230+
echo "$result"
231+
echo "$result" | grep -oE "<meta name=\"title\" [^>]*>" | grep "University Research Fellowship"
232+
233+
# Get a specific orgunit in our test data and verify that the <meta name="title"> tag includes
234+
# the name of the orgunit. If it does, then SSR is working.
235+
- name: Verify SSR on an OrgUnit page
236+
run: |
237+
result=$(wget -O- -q http://127.0.0.1:4000/entities/orgunit/9851674d-bd9a-467b-8d84-068deb568ccf)
238+
echo "$result"
239+
echo "$result" | grep -oE "<meta name=\"title\" [^>]*>" | grep "Law and Development"
240+
241+
# Get a specific journal in our test data and verify that the <meta name="title"> tag includes
242+
# the name of the journal. If it does, then SSR is working.
243+
- name: Verify SSR on a Journal page
244+
run: |
245+
result=$(wget -O- -q http://127.0.0.1:4000/entities/journal/d4af6c3e-53d0-4757-81eb-566f3b45d63a)
246+
echo "$result"
247+
echo "$result" | grep -oE "<meta name=\"title\" [^>]*>" | grep "Environmental &amp; Architectural Phenomenology"
248+
249+
# Get a specific journal volume in our test data and verify that the <meta name="title"> tag includes
250+
# the name of the volume. If it does, then SSR is working.
251+
- name: Verify SSR on a Journal Volume page
252+
run: |
253+
result=$(wget -O- -q http://127.0.0.1:4000/entities/journalvolume/07c6249f-4bf7-494d-9ce3-6ffdb2aed538)
254+
echo "$result"
255+
echo "$result" | grep -oE "<meta name=\"title\" [^>]*>" | grep "Environmental &amp; Architectural Phenomenology Volume 28 (2017)"
256+
257+
# Get a specific journal issue in our test data and verify that the <meta name="title"> tag includes
258+
# the name of the issue. If it does, then SSR is working.
259+
- name: Verify SSR on a Journal Issue page
260+
run: |
261+
result=$(wget -O- -q http://127.0.0.1:4000/entities/journalissue/44c29473-5de2-48fa-b005-e5029aa1a50b)
262+
echo "$result"
263+
echo "$result" | grep -oE "<meta name=\"title\" [^>]*>" | grep "Environmental &amp; Architectural Phenomenology Vol. 28, No. 1"
264+
193265
- name: Stop running app
194266
run: kill -9 $(lsof -t -i:4000)
195267

package.json

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
"@angular/platform-browser-dynamic": "^15.2.10",
6161
"@angular/platform-server": "^15.2.10",
6262
"@angular/router": "^15.2.10",
63-
"@babel/runtime": "7.26.7",
63+
"@babel/runtime": "7.27.0",
6464
"@kolkov/ngx-gallery": "^2.0.1",
6565
"@ng-bootstrap/ng-bootstrap": "^11.0.0",
6666
"@ng-dynamic-forms/core": "^15.0.0",
@@ -73,14 +73,14 @@
7373
"@nicky-lenaers/ngx-scroll-to": "^14.0.0",
7474
"angular-idle-preload": "3.0.0",
7575
"angulartics2": "^12.2.1",
76-
"axios": "^1.7.9",
76+
"axios": "^1.8.4",
7777
"bootstrap": "^4.6.1",
7878
"cerialize": "0.1.18",
7979
"cli-progress": "^3.12.0",
8080
"colors": "^1.4.0",
81-
"compression": "^1.7.5",
81+
"compression": "^1.8.0",
8282
"cookie-parser": "1.4.7",
83-
"core-js": "^3.40.0",
83+
"core-js": "^3.41.0",
8484
"date-fns": "^2.30.0",
8585
"date-fns-tz": "^1.3.7",
8686
"deepmerge": "^4.3.1",
@@ -89,9 +89,9 @@
8989
"express-rate-limit": "^5.1.3",
9090
"fast-json-patch": "^3.1.1",
9191
"filesize": "^6.1.0",
92-
"http-proxy-middleware": "^2.0.7",
92+
"http-proxy-middleware": "^2.0.9",
9393
"http-terminator": "^3.2.0",
94-
"isbot": "^5.1.22",
94+
"isbot": "^5.1.26",
9595
"js-cookie": "2.2.1",
9696
"js-yaml": "^4.1.0",
9797
"json5": "^2.2.3",
@@ -116,8 +116,8 @@
116116
"nouislider": "^15.8.1",
117117
"pem": "1.14.8",
118118
"reflect-metadata": "^0.2.2",
119-
"rxjs": "^7.8.0",
120-
"sanitize-html": "^2.14.0",
119+
"rxjs": "^7.8.2",
120+
"sanitize-html": "^2.16.0",
121121
"sortablejs": "1.15.6",
122122
"uuid": "^8.3.2",
123123
"zone.js": "~0.13.3"
@@ -146,12 +146,12 @@
146146
"@types/grecaptcha": "^3.0.9",
147147
"@types/jasmine": "~3.6.0",
148148
"@types/js-cookie": "2.2.6",
149-
"@types/lodash": "^4.17.15",
149+
"@types/lodash": "^4.17.16",
150150
"@types/node": "^14.18.63",
151-
"@types/sanitize-html": "^2.13.0",
151+
"@types/sanitize-html": "^2.15.0",
152152
"@typescript-eslint/eslint-plugin": "^5.62.0",
153153
"@typescript-eslint/parser": "^5.62.0",
154-
"axe-core": "^4.10.2",
154+
"axe-core": "^4.10.3",
155155
"compression-webpack-plugin": "^9.2.0",
156156
"copy-webpack-plugin": "^6.4.1",
157157
"cross-env": "^7.0.3",
@@ -163,7 +163,7 @@
163163
"eslint-plugin-deprecation": "^1.5.0",
164164
"eslint-plugin-import": "^2.31.0",
165165
"eslint-plugin-jsdoc": "^45.0.0",
166-
"eslint-plugin-jsonc": "^2.19.1",
166+
"eslint-plugin-jsonc": "^2.20.0",
167167
"eslint-plugin-lodash": "^7.4.0",
168168
"eslint-plugin-unused-imports": "^2.0.0",
169169
"express-static-gzip": "^2.2.0",
@@ -175,7 +175,7 @@
175175
"karma-jasmine": "~4.0.0",
176176
"karma-jasmine-html-reporter": "^1.5.0",
177177
"karma-mocha-reporter": "2.2.5",
178-
"ng-mocks": "^14.13.2",
178+
"ng-mocks": "^14.13.4",
179179
"ngx-mask": "^13.1.7",
180180
"nodemon": "^2.0.22",
181181
"postcss": "^8.5",
@@ -187,7 +187,7 @@
187187
"react-copy-to-clipboard": "^5.1.0",
188188
"react-dom": "^16.14.0",
189189
"rimraf": "^3.0.2",
190-
"sass": "~1.84.0",
190+
"sass": "~1.86.3",
191191
"sass-loader": "^12.6.0",
192192
"sass-resources-loader": "^2.2.5",
193193
"ts-node": "^8.10.2",

src/app/access-control/bulk-access/bulk-access.component.spec.ts

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { ComponentFixture, TestBed } from '@angular/core/testing';
2-
import { NO_ERRORS_SCHEMA } from '@angular/core';
2+
import { NO_ERRORS_SCHEMA, Component } from '@angular/core';
33

44
import { TranslateModule } from '@ngx-translate/core';
55
import { of } from 'rxjs';
@@ -57,10 +57,15 @@ describe('BulkAccessComponent', () => {
5757
'file': { }
5858
};
5959

60-
const mockSettings: any = jasmine.createSpyObj('AccessControlFormContainerComponent', {
61-
getValue: jasmine.createSpy('getValue'),
62-
reset: jasmine.createSpy('reset')
63-
});
60+
@Component({
61+
selector: 'ds-bulk-access-settings',
62+
template: ''
63+
})
64+
class MockBulkAccessSettingsComponent {
65+
isFormValid = jasmine.createSpy('isFormValid').and.returnValue(false);
66+
getValue = jasmine.createSpy('getValue');
67+
reset = jasmine.createSpy('reset');
68+
}
6469
const selection: any[] = [{ indexableObject: { uuid: '1234' } }, { indexableObject: { uuid: '5678' } }];
6570
const selectableListState: SelectableListState = { id: 'test', selection };
6671
const expectedIdList = ['1234', '5678'];
@@ -73,7 +78,10 @@ describe('BulkAccessComponent', () => {
7378
RouterTestingModule,
7479
TranslateModule.forRoot()
7580
],
76-
declarations: [ BulkAccessComponent ],
81+
declarations: [
82+
BulkAccessComponent,
83+
MockBulkAccessSettingsComponent,
84+
],
7785
providers: [
7886
{ provide: BulkAccessControlService, useValue: bulkAccessControlServiceMock },
7987
{ provide: NotificationsService, useValue: NotificationsServiceStub },
@@ -102,7 +110,6 @@ describe('BulkAccessComponent', () => {
102110

103111
(component as any).selectableListService.getSelectableList.and.returnValue(of(selectableListStateEmpty));
104112
fixture.detectChanges();
105-
component.settings = mockSettings;
106113
});
107114

108115
it('should create', () => {
@@ -119,13 +126,12 @@ describe('BulkAccessComponent', () => {
119126

120127
});
121128

122-
describe('when there are elements selected', () => {
129+
describe('when there are elements selected and step two form is invalid', () => {
123130

124131
beforeEach(() => {
125132

126133
(component as any).selectableListService.getSelectableList.and.returnValue(of(selectableListState));
127134
fixture.detectChanges();
128-
component.settings = mockSettings;
129135
});
130136

131137
it('should create', () => {
@@ -136,16 +142,33 @@ describe('BulkAccessComponent', () => {
136142
expect(component.objectsSelected$.value).toEqual(expectedIdList);
137143
});
138144

139-
it('should enable the execute button when there are objects selected', () => {
145+
it('should not enable the execute button when there are objects selected and step two form is invalid', () => {
140146
component.objectsSelected$.next(['1234']);
141-
expect(component.canExport()).toBe(true);
147+
expect(component.canExport()).toBe(false);
142148
});
143149

144150
it('should call the settings reset method when reset is called', () => {
145151
component.reset();
146152
expect(component.settings.reset).toHaveBeenCalled();
147153
});
148154

155+
156+
});
157+
158+
describe('when there are elements selectedted and the step two form is valid', () => {
159+
160+
beforeEach(() => {
161+
162+
(component as any).selectableListService.getSelectableList.and.returnValue(of(selectableListState));
163+
fixture.detectChanges();
164+
(component as any).settings.isFormValid.and.returnValue(true);
165+
});
166+
167+
it('should enable the execute button when there are objects selected and step two form is valid', () => {
168+
component.objectsSelected$.next(['1234']);
169+
expect(component.canExport()).toBe(true);
170+
});
171+
149172
it('should call the bulkAccessControlService executeScript method when submit is called', () => {
150173
(component.settings as any).getValue.and.returnValue(mockFormState);
151174
bulkAccessControlService.createPayloadFile.and.returnValue(mockFile);

src/app/access-control/bulk-access/bulk-access.component.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export class BulkAccessComponent implements OnInit {
3737

3838
constructor(
3939
private bulkAccessControlService: BulkAccessControlService,
40-
private selectableListService: SelectableListService
40+
private selectableListService: SelectableListService,
4141
) {
4242
}
4343

@@ -51,7 +51,7 @@ export class BulkAccessComponent implements OnInit {
5151
}
5252

5353
canExport(): boolean {
54-
return this.objectsSelected$.value?.length > 0;
54+
return this.objectsSelected$.value?.length > 0 && this.settings?.isFormValid();
5555
}
5656

5757
/**

src/app/access-control/bulk-access/settings/bulk-access-settings.component.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,8 @@ export class BulkAccessSettingsComponent {
3131
this.controlForm.reset();
3232
}
3333

34+
isFormValid() {
35+
return this.controlForm.isValid();
36+
}
37+
3438
}

src/app/core/auth/auth.service.spec.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ describe('AuthService test', () => {
260260
(state as any).core = Object.create({});
261261
(state as any).core.auth = authenticatedState;
262262
});
263-
authService = new AuthService({}, window, undefined, authReqService, mockEpersonDataService, router, routeService, cookieService, store, hardRedirectService, notificationsService, translateService);
263+
authService = new AuthService(window, authReqService, mockEpersonDataService, router, routeService, cookieService, store, hardRedirectService, notificationsService, translateService);
264264
}));
265265

266266
it('should return true when user is logged in', () => {
@@ -345,7 +345,7 @@ describe('AuthService test', () => {
345345
(state as any).core = Object.create({});
346346
(state as any).core.auth = authenticatedState;
347347
});
348-
authService = new AuthService({}, window, undefined, authReqService, mockEpersonDataService, router, routeService, cookieService, store, hardRedirectService, notificationsService, translateService);
348+
authService = new AuthService(window, authReqService, mockEpersonDataService, router, routeService, cookieService, store, hardRedirectService, notificationsService, translateService);
349349
storage = (authService as any).storage;
350350
routeServiceMock = TestBed.inject(RouteService);
351351
routerStub = TestBed.inject(Router);
@@ -565,7 +565,7 @@ describe('AuthService test', () => {
565565
(state as any).core = Object.create({});
566566
(state as any).core.auth = unAuthenticatedState;
567567
});
568-
authService = new AuthService({}, window, undefined, authReqService, mockEpersonDataService, router, routeService, cookieService, store, hardRedirectService, notificationsService, translateService);
568+
authService = new AuthService(window, authReqService, mockEpersonDataService, router, routeService, cookieService, store, hardRedirectService, notificationsService, translateService);
569569
}));
570570

571571
it('should return null for the shortlived token', () => {
@@ -605,7 +605,7 @@ describe('AuthService test', () => {
605605
(state as any).core = Object.create({});
606606
(state as any).core.auth = idleState;
607607
});
608-
authService = new AuthService({}, window, undefined, authReqService, mockEpersonDataService, router, routeService, cookieService, store, hardRedirectService, notificationsService, translateService);
608+
authService = new AuthService(window, authReqService, mockEpersonDataService, router, routeService, cookieService, store, hardRedirectService, notificationsService, translateService);
609609
}));
610610

611611
it('isUserIdle should return true when user is not idle', () => {

0 commit comments

Comments
 (0)