mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
Merge pull request #1282 from tdonohue/test_ssr_working
SEO + SSR fixes: Fix <meta> tag syntax and add a basic test that SSR is working
This commit is contained in:
23
.github/workflows/build.yml
vendored
23
.github/workflows/build.yml
vendored
@@ -117,5 +117,28 @@ jobs:
|
|||||||
chromedriver --url-base='/wd/hub' --port=4444 &
|
chromedriver --url-base='/wd/hub' --port=4444 &
|
||||||
yarn run e2e:ci
|
yarn run e2e:ci
|
||||||
|
|
||||||
|
# Start up the app with SSR enabled (run in background)
|
||||||
|
- name: Start app in SSR (server-side rendering) mode
|
||||||
|
run: |
|
||||||
|
nohup yarn run serve:ssr &
|
||||||
|
printf 'Waiting for app to start'
|
||||||
|
until curl --output /dev/null --silent --head --fail http://localhost:4000/home; do
|
||||||
|
printf '.'
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
echo "App started successfully."
|
||||||
|
|
||||||
|
# Get homepage and verify that the <meta name="title"> tag includes "DSpace".
|
||||||
|
# If it does, then SSR is working, as this tag is created by our MetadataService.
|
||||||
|
# This step also prints entire HTML of homepage for easier debugging if grep fails.
|
||||||
|
- name: Verify SSR (server-side rendering)
|
||||||
|
run: |
|
||||||
|
result=$(wget -O- -q http://localhost:4000/home)
|
||||||
|
echo "$result"
|
||||||
|
echo "$result" | grep -oE "<meta name=\"title\" [^>]*>" | grep DSpace
|
||||||
|
|
||||||
|
- name: Stop running app
|
||||||
|
run: kill -9 $(lsof -t -i:4000)
|
||||||
|
|
||||||
- name: Shutdown Docker containers
|
- name: Shutdown Docker containers
|
||||||
run: docker-compose -f ./docker/docker-compose-ci.yml down
|
run: docker-compose -f ./docker/docker-compose-ci.yml down
|
||||||
|
@@ -107,18 +107,18 @@ describe('MetadataService', () => {
|
|||||||
tick();
|
tick();
|
||||||
expect(title.setTitle).toHaveBeenCalledWith('Test PowerPoint Document');
|
expect(title.setTitle).toHaveBeenCalledWith('Test PowerPoint Document');
|
||||||
expect(meta.addTag).toHaveBeenCalledWith({
|
expect(meta.addTag).toHaveBeenCalledWith({
|
||||||
property: 'citation_title',
|
name: 'citation_title',
|
||||||
content: 'Test PowerPoint Document'
|
content: 'Test PowerPoint Document'
|
||||||
});
|
});
|
||||||
expect(meta.addTag).toHaveBeenCalledWith({ property: 'citation_author', content: 'Doe, Jane' });
|
expect(meta.addTag).toHaveBeenCalledWith({ name: 'citation_author', content: 'Doe, Jane' });
|
||||||
expect(meta.addTag).toHaveBeenCalledWith({
|
expect(meta.addTag).toHaveBeenCalledWith({
|
||||||
property: 'citation_publication_date',
|
name: 'citation_publication_date',
|
||||||
content: '1650-06-26'
|
content: '1650-06-26'
|
||||||
});
|
});
|
||||||
expect(meta.addTag).toHaveBeenCalledWith({ property: 'citation_issn', content: '123456789' });
|
expect(meta.addTag).toHaveBeenCalledWith({ name: 'citation_issn', content: '123456789' });
|
||||||
expect(meta.addTag).toHaveBeenCalledWith({ property: 'citation_language', content: 'en' });
|
expect(meta.addTag).toHaveBeenCalledWith({ name: 'citation_language', content: 'en' });
|
||||||
expect(meta.addTag).toHaveBeenCalledWith({
|
expect(meta.addTag).toHaveBeenCalledWith({
|
||||||
property: 'citation_keywords',
|
name: 'citation_keywords',
|
||||||
content: 'keyword1; keyword2; keyword3'
|
content: 'keyword1; keyword2; keyword3'
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
@@ -133,11 +133,11 @@ describe('MetadataService', () => {
|
|||||||
});
|
});
|
||||||
tick();
|
tick();
|
||||||
expect(meta.addTag).toHaveBeenCalledWith({
|
expect(meta.addTag).toHaveBeenCalledWith({
|
||||||
property: 'citation_dissertation_name',
|
name: 'citation_dissertation_name',
|
||||||
content: 'Test PowerPoint Document'
|
content: 'Test PowerPoint Document'
|
||||||
});
|
});
|
||||||
expect(meta.addTag).toHaveBeenCalledWith({
|
expect(meta.addTag).toHaveBeenCalledWith({
|
||||||
property: 'citation_pdf_url',
|
name: 'citation_pdf_url',
|
||||||
content: 'https://request.org/bitstreams/4db100c1-e1f5-4055-9404-9bc3e2d15f29/download'
|
content: 'https://request.org/bitstreams/4db100c1-e1f5-4055-9404-9bc3e2d15f29/download'
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
@@ -152,7 +152,7 @@ describe('MetadataService', () => {
|
|||||||
});
|
});
|
||||||
tick();
|
tick();
|
||||||
expect(meta.addTag).toHaveBeenCalledWith({
|
expect(meta.addTag).toHaveBeenCalledWith({
|
||||||
property: 'citation_technical_report_institution',
|
name: 'citation_technical_report_institution',
|
||||||
content: 'Mock Publisher'
|
content: 'Mock Publisher'
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
@@ -170,11 +170,11 @@ describe('MetadataService', () => {
|
|||||||
tick();
|
tick();
|
||||||
expect(title.setTitle).toHaveBeenCalledWith('DSpace :: Dummy Title');
|
expect(title.setTitle).toHaveBeenCalledWith('DSpace :: Dummy Title');
|
||||||
expect(meta.addTag).toHaveBeenCalledWith({
|
expect(meta.addTag).toHaveBeenCalledWith({
|
||||||
property: 'title',
|
name: 'title',
|
||||||
content: 'DSpace :: Dummy Title'
|
content: 'DSpace :: Dummy Title'
|
||||||
});
|
});
|
||||||
expect(meta.addTag).toHaveBeenCalledWith({
|
expect(meta.addTag).toHaveBeenCalledWith({
|
||||||
property: 'description',
|
name: 'description',
|
||||||
content: 'This is a dummy item component for testing!'
|
content: 'This is a dummy item component for testing!'
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
@@ -191,7 +191,7 @@ describe('MetadataService', () => {
|
|||||||
metadataService.listenForRouteChange();
|
metadataService.listenForRouteChange();
|
||||||
tick();
|
tick();
|
||||||
expect(meta.addTag).toHaveBeenCalledWith({
|
expect(meta.addTag).toHaveBeenCalledWith({
|
||||||
property: 'Generator',
|
name: 'Generator',
|
||||||
content: 'mock-dspace-version'
|
content: 'mock-dspace-version'
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
@@ -208,7 +208,7 @@ describe('MetadataService', () => {
|
|||||||
});
|
});
|
||||||
tick();
|
tick();
|
||||||
expect(meta.addTag).toHaveBeenCalledWith({
|
expect(meta.addTag).toHaveBeenCalledWith({
|
||||||
property: 'citation_abstract_html_url',
|
name: 'citation_abstract_html_url',
|
||||||
content: 'https://ddg.gg'
|
content: 'https://ddg.gg'
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
@@ -223,7 +223,7 @@ describe('MetadataService', () => {
|
|||||||
});
|
});
|
||||||
tick();
|
tick();
|
||||||
expect(meta.addTag).toHaveBeenCalledWith({
|
expect(meta.addTag).toHaveBeenCalledWith({
|
||||||
property: 'citation_abstract_html_url',
|
name: 'citation_abstract_html_url',
|
||||||
content: 'https://request.org/items/0ec7ff22-f211-40ab-a69e-c819b0b1f357'
|
content: 'https://request.org/items/0ec7ff22-f211-40ab-a69e-c819b0b1f357'
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
@@ -240,11 +240,11 @@ describe('MetadataService', () => {
|
|||||||
});
|
});
|
||||||
tick();
|
tick();
|
||||||
expect(meta.addTag).toHaveBeenCalledWith({
|
expect(meta.addTag).toHaveBeenCalledWith({
|
||||||
property: 'citation_dissertation_institution',
|
name: 'citation_dissertation_institution',
|
||||||
content: 'Mock Publisher'
|
content: 'Mock Publisher'
|
||||||
});
|
});
|
||||||
expect(meta.addTag).not.toHaveBeenCalledWith(jasmine.objectContaining({ property: 'citation_technical_report_institution' }));
|
expect(meta.addTag).not.toHaveBeenCalledWith(jasmine.objectContaining({ name: 'citation_technical_report_institution' }));
|
||||||
expect(meta.addTag).not.toHaveBeenCalledWith(jasmine.objectContaining({ property: 'citation_publisher' }));
|
expect(meta.addTag).not.toHaveBeenCalledWith(jasmine.objectContaining({ name: 'citation_publisher' }));
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should use citation_tech_report_institution tag for tech reports', fakeAsync(() => {
|
it('should use citation_tech_report_institution tag for tech reports', fakeAsync(() => {
|
||||||
@@ -256,12 +256,12 @@ describe('MetadataService', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
tick();
|
tick();
|
||||||
expect(meta.addTag).not.toHaveBeenCalledWith(jasmine.objectContaining({ property: 'citation_dissertation_institution' }));
|
expect(meta.addTag).not.toHaveBeenCalledWith(jasmine.objectContaining({ name: 'citation_dissertation_institution' }));
|
||||||
expect(meta.addTag).toHaveBeenCalledWith({
|
expect(meta.addTag).toHaveBeenCalledWith({
|
||||||
property: 'citation_technical_report_institution',
|
name: 'citation_technical_report_institution',
|
||||||
content: 'Mock Publisher'
|
content: 'Mock Publisher'
|
||||||
});
|
});
|
||||||
expect(meta.addTag).not.toHaveBeenCalledWith(jasmine.objectContaining({ property: 'citation_publisher' }));
|
expect(meta.addTag).not.toHaveBeenCalledWith(jasmine.objectContaining({ name: 'citation_publisher' }));
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should use citation_publisher for other item types', fakeAsync(() => {
|
it('should use citation_publisher for other item types', fakeAsync(() => {
|
||||||
@@ -273,10 +273,10 @@ describe('MetadataService', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
tick();
|
tick();
|
||||||
expect(meta.addTag).not.toHaveBeenCalledWith(jasmine.objectContaining({ property: 'citation_dissertation_institution' }));
|
expect(meta.addTag).not.toHaveBeenCalledWith(jasmine.objectContaining({ name: 'citation_dissertation_institution' }));
|
||||||
expect(meta.addTag).not.toHaveBeenCalledWith(jasmine.objectContaining({ property: 'citation_technical_report_institution' }));
|
expect(meta.addTag).not.toHaveBeenCalledWith(jasmine.objectContaining({ name: 'citation_technical_report_institution' }));
|
||||||
expect(meta.addTag).toHaveBeenCalledWith({
|
expect(meta.addTag).toHaveBeenCalledWith({
|
||||||
property: 'citation_publisher',
|
name: 'citation_publisher',
|
||||||
content: 'Mock Publisher'
|
content: 'Mock Publisher'
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
@@ -295,7 +295,7 @@ describe('MetadataService', () => {
|
|||||||
});
|
});
|
||||||
tick();
|
tick();
|
||||||
expect(meta.addTag).toHaveBeenCalledWith({
|
expect(meta.addTag).toHaveBeenCalledWith({
|
||||||
property: 'citation_pdf_url',
|
name: 'citation_pdf_url',
|
||||||
content: 'https://request.org/bitstreams/4db100c1-e1f5-4055-9404-9bc3e2d15f29/download'
|
content: 'https://request.org/bitstreams/4db100c1-e1f5-4055-9404-9bc3e2d15f29/download'
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
@@ -313,7 +313,7 @@ describe('MetadataService', () => {
|
|||||||
});
|
});
|
||||||
tick();
|
tick();
|
||||||
expect(meta.addTag).toHaveBeenCalledWith({
|
expect(meta.addTag).toHaveBeenCalledWith({
|
||||||
property: 'citation_pdf_url',
|
name: 'citation_pdf_url',
|
||||||
content: 'https://request.org/bitstreams/4db100c1-e1f5-4055-9404-9bc3e2d15f29/download'
|
content: 'https://request.org/bitstreams/4db100c1-e1f5-4055-9404-9bc3e2d15f29/download'
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
@@ -334,7 +334,7 @@ describe('MetadataService', () => {
|
|||||||
});
|
});
|
||||||
tick();
|
tick();
|
||||||
expect(meta.addTag).toHaveBeenCalledWith({
|
expect(meta.addTag).toHaveBeenCalledWith({
|
||||||
property: 'citation_pdf_url',
|
name: 'citation_pdf_url',
|
||||||
content: 'https://request.org/bitstreams/cf9b0c8e-a1eb-4b65-afd0-567366448713/download'
|
content: 'https://request.org/bitstreams/cf9b0c8e-a1eb-4b65-afd0-567366448713/download'
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
@@ -354,8 +354,8 @@ describe('MetadataService', () => {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
it('should remove previous tags on route change', fakeAsync(() => {
|
it('should remove previous tags on route change', fakeAsync(() => {
|
||||||
expect(meta.removeTag).toHaveBeenCalledWith('property=\'title\'');
|
expect(meta.removeTag).toHaveBeenCalledWith('name=\'title\'');
|
||||||
expect(meta.removeTag).toHaveBeenCalledWith('property=\'description\'');
|
expect(meta.removeTag).toHaveBeenCalledWith('name=\'description\'');
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should clear all tags and add new ones on route change', () => {
|
it('should clear all tags and add new ones on route change', () => {
|
||||||
|
@@ -403,7 +403,7 @@ export class MetadataService {
|
|||||||
*/
|
*/
|
||||||
private setGenerator(): void {
|
private setGenerator(): void {
|
||||||
this.rootService.findRoot().pipe(getFirstSucceededRemoteDataPayload()).subscribe((root) => {
|
this.rootService.findRoot().pipe(getFirstSucceededRemoteDataPayload()).subscribe((root) => {
|
||||||
this.meta.addTag({ property: 'Generator', content: root.dspaceVersion });
|
this.meta.addTag({ name: 'Generator', content: root.dspaceVersion });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -447,17 +447,17 @@ export class MetadataService {
|
|||||||
return this.currentObject.value.allMetadataValues(keys);
|
return this.currentObject.value.allMetadataValues(keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
private addMetaTag(property: string, content: string): void {
|
private addMetaTag(name: string, content: string): void {
|
||||||
if (content) {
|
if (content) {
|
||||||
const tag = { property, content } as MetaDefinition;
|
const tag = { name, content } as MetaDefinition;
|
||||||
this.meta.addTag(tag);
|
this.meta.addTag(tag);
|
||||||
this.storeTag(property);
|
this.storeTag(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private addMetaTags(property: string, content: string[]): void {
|
private addMetaTags(name: string, content: string[]): void {
|
||||||
for (const value of content) {
|
for (const value of content) {
|
||||||
this.addMetaTag(property, value);
|
this.addMetaTag(name, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -470,8 +470,8 @@ export class MetadataService {
|
|||||||
select(tagsInUseSelector),
|
select(tagsInUseSelector),
|
||||||
take(1)
|
take(1)
|
||||||
).subscribe((tagsInUse: string[]) => {
|
).subscribe((tagsInUse: string[]) => {
|
||||||
for (const property of tagsInUse) {
|
for (const name of tagsInUse) {
|
||||||
this.meta.removeTag('property=\'' + property + '\'');
|
this.meta.removeTag('name=\'' + name + '\'');
|
||||||
}
|
}
|
||||||
this.store.dispatch(new ClearMetaTagAction());
|
this.store.dispatch(new ClearMetaTagAction());
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user