Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,61 @@ <h3 class="orc-font-body" i18n="@@register.affiliationFoud">
<div>
<p class="main-paragraph">
<ng-container i18n="@@register.basedOnYourEmailWeThink">
Based on your emails we think you are currently affiliated with
Based on your email address we think you are currently affiliated
with
</ng-container>
<strong> {{ autoCompleteDisplayOrganization(organization) }}.</strong>

<ng-container
i18n="
@@register.webePreselectedThisOrganizationForYouInTheFormBelow"
>
We’ve pre-selected this organization for you in the form
below.</ng-container
<em
><ng-container
i18n="
@@register.webePreselectedThisOrganizationForYouInTheFormBelow"
>
We’ve pre-selected this organization for you in the form
below.</ng-container
></em
>
</p>

<div i18n="@@register.whenYouCompleteRegistrationAnEmployment">
When you complete registration an employment affiliation will be
automatically added to your new ORCID record.
When you complete registration your affiliation will be automatically
added to your new ORCID record.
</div>
</div>
</div>
</div>

<div class="info" *ngIf="!rorIdHasBeenMatched" id="step-c2-not-ready-notice">
<mat-icon aria-hidden="true">info_outline</mat-icon>
<div class="content">
<div>
<h3
class="orc-font-body"
i18n="@@register.notReadyToAddYourAffiliation"
>
Not ready to add your affiliation?
</h3>
</div>
<div>
<p
class="main-paragraph"
i18n="@@register.youDontNeedToAddAnAffiliation"
>
You don’t need to add an affiliation to complete registration and get
your ORCID record and iD.
</p>
<p>
<a
id="step-c2-notice-skip-link"
(click)="skipFromNoticePanel()"
i18n="@@register.skipThisStepAndContinueRegistration"
>Skip this step and continue registration</a
>
</p>
</div>
</div>
</div>

<section id="{{ type }}-organization">
<div
id="organization"
Expand Down Expand Up @@ -85,6 +119,7 @@ <h3 class="orc-font-body" i18n="@@register.affiliationFoud">
formControlName="organization"
[matAutocomplete]="auto"
[attr.aria-invalid]="organizationIsInvalidAndTouched"
aria-describedby="organization-not-found-error organization-required-error"
[placeholder]="organizationPlaceholder"
/>
<mat-autocomplete
Expand Down Expand Up @@ -141,10 +176,19 @@ <h3 class="orc-font-body" i18n="@@register.affiliationFoud">
organizationIsInvalidAndTouched &&
displayOrganizationHint
"
i18n="@@register.weCantIdentifyThisOrganization"
id="organization-not-found-error"
role="alert"
>
We can’t identify this organization. Please try entering the
organization name again.
<ng-container i18n="@@register.thisOrganizationIsNotInOurDatabase"
>This organization is not in our database. Please try entering the
name again. If you cannot find your organization you can</ng-container
>
<a
id="step-c2-error-skip-link"
(click)="skipFromOrganizationError()"
i18n="@@register.skipThisStep"
>skip this step</a
>
</div>
<div
class="selected-org orc-font-small-print error"
Expand All @@ -154,6 +198,8 @@ <h3 class="orc-font-body" i18n="@@register.affiliationFoud">
organizationIsInvalidAndTouched &&
!displayOrganizationHint
"
id="organization-required-error"
role="alert"
i18n="@@register.pleaseEnterAnOrganizationName"
>
Please enter an organization name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ import {
import { SharedModule } from 'src/app/shared/shared.module'

import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'
import { RegisterObservabilityService } from '../../register-observability.service'

describe('FormPersonalComponent', () => {
describe('FormCurrentEmploymentComponent', () => {
let component: FormCurrentEmploymentComponent
let fixture: ComponentFixture<FormCurrentEmploymentComponent>

Expand Down Expand Up @@ -59,4 +60,82 @@ describe('FormPersonalComponent', () => {
it('should create', () => {
expect(component).toBeTruthy()
})

describe('the "not ready to add your affiliation" notice', () => {
const notice = () =>
fixture.nativeElement.querySelector('#step-c2-not-ready-notice')

it('is shown while no affiliation has been suggested', () => {
expect(component.rorIdHasBeenMatched).toBeUndefined()
expect(notice()).toBeTruthy()
expect(notice().textContent).toContain(
'Not ready to add your affiliation?'
)
})

it('is hidden once an affiliation has been matched', () => {
component.rorIdHasBeenMatched = true
fixture.detectChanges()

expect(notice()).toBeNull()
})

it('comes back when the matched organization is cleared', () => {
component.rorIdHasBeenMatched = true
fixture.detectChanges()

component.clearForm()
fixture.detectChanges()

expect(notice()).toBeTruthy()
})

it('skips the step and reports it', () => {
const observability = TestBed.inject(RegisterObservabilityService)
spyOn(observability, 'stepC2NoticeSkipLinkClicked')
const skipStep = jasmine.createSpy('skipStep')
component.skipStep.subscribe(skipStep)

fixture.nativeElement.querySelector('#step-c2-notice-skip-link').click()

expect(observability.stepC2NoticeSkipLinkClicked).toHaveBeenCalled()
expect(skipStep).toHaveBeenCalled()
})
})

describe('the unidentified organization error', () => {
beforeEach(() => {
component.form.get('organization').setValue('university of b')
component.form.get('organization').markAsTouched()
component.selectedOrganizationFromDatabase = undefined
component.displayOrganizationHint = true
fixture.detectChanges()
})

const error = () =>
fixture.nativeElement.querySelector('#organization-not-found-error')

it('tells the user the organization is unknown and can be skipped', () => {
expect(error()).toBeTruthy()
expect(error().getAttribute('role')).toBe('alert')
expect(error().textContent).toContain(
'This organization is not in our database.'
)
expect(
error().querySelector('#step-c2-error-skip-link').textContent
).toContain('skip this step')
})

it('skips the step and reports it', () => {
const observability = TestBed.inject(RegisterObservabilityService)
spyOn(observability, 'stepC2ErrorSkipLinkClicked')
const skipStep = jasmine.createSpy('skipStep')
component.skipStep.subscribe(skipStep)

error().querySelector('#step-c2-error-skip-link').click()

expect(observability.stepC2ErrorSkipLinkClicked).toHaveBeenCalled()
expect(skipStep).toHaveBeenCalled()
})
})
})
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import {
Component,
EventEmitter,
forwardRef,
Input,
OnDestroy,
OnInit,
Output,
ViewChild,
} from '@angular/core'
import {
Expand Down Expand Up @@ -100,6 +102,7 @@ export class FormCurrentEmploymentComponent

nextButtonWasClicked: boolean
@Input() reactivation: ReactivationLocal
@Output() skipStep = new EventEmitter<void>()
@ViewChild(FormGroupDirective) formGroupDir: FormGroupDirective
ariaLabelClearOrganization = $localize`:@@register.clearOrganization:Clear organization`
organizationPlaceholder = $localize`:@@register.organizationPlaceholder:Type your organization name`
Expand Down Expand Up @@ -286,6 +289,16 @@ export class FormCurrentEmploymentComponent
this.form.controls.organization.markAsUntouched()
}

skipFromNoticePanel() {
this._registerObservabilityService.stepC2NoticeSkipLinkClicked(this.form)
this.skipStep.emit()
}

skipFromOrganizationError() {
this._registerObservabilityService.stepC2ErrorSkipLinkClicked(this.form)
this.skipStep.emit()
}

// OVERWRITE
registerOnChange(fn: any) {
this.form.valueChanges.subscribe((value) => {
Expand Down
3 changes: 3 additions & 0 deletions src/app/register/components/register.style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,9 @@ mat-label.orc-font-small-print {
mat-icon,
img {
margin-right: 16px;
// Direct flex children, so without this the icon is squeezed below its
// 24px glyph box and renders as a clipped sliver.
flex-shrink: 0;
}

h3 {
Expand Down
17 changes: 11 additions & 6 deletions src/app/register/components/step-c2/step-c2.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,27 @@ <h1 class="orc-font-heading-small" i18n="@@register.create">
</ng-container>
</mat-card-title>
<mat-card-subtitle role="heading" aria-level="2">
<h2 class="orc-font-body-small" i18n="@@register.step3.3">
Step 3 of 5 - Current employment
<h2 class="orc-font-body-small">
<ng-container i18n="@@register.step3.3"
>Step 3 of 5 - Current employment</ng-container
>&ngsp;<em i18n="@@register.optional">(Optional)</em>
</h2>
</mat-card-subtitle>
</mat-card-header>

<mat-card-content>
<p *ngIf="!reactivation?.isReactivation">
<p
*ngIf="!reactivation?.isReactivation"
i18n="@@register.addingACurrentEmploymentAffiliationHelps"
>
Adding a current employment affiliation helps distinguish you from other
researchers with a similar name.
</p>

<form [formGroup]="formGroup" #form>
<app-form-current-employment
formControlName="affiliations"
(skipStep)="optionalNextStep()"
></app-form-current-employment>
<div class="step-actions margin-top-12">
<button
Expand All @@ -63,10 +69,9 @@ <h2 class="orc-font-body-small" i18n="@@register.step3.3">
(click)="optionalNextStep()"
>
<a
i18n="@@shared.skipThisStepWithoutAddingAnAffiliation"
i18n="@@register.skipThisStepAndContinueRegistration"
class="skip-step"
>
Skip this step without adding an affiliation</a
>Skip this step and continue registration</a
>
</button>
<button
Expand Down
62 changes: 59 additions & 3 deletions src/app/register/components/step-c2/step-c2.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,21 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'

import { StepC2Component } from './step-c2.component'

import { Component, CUSTOM_ELEMENTS_SCHEMA, forwardRef } from '@angular/core'
import {
Component,
CUSTOM_ELEMENTS_SCHEMA,
EventEmitter,
forwardRef,
Output,
} from '@angular/core'
import {
ControlValueAccessor,
NG_VALUE_ACCESSOR,
ReactiveFormsModule,
UntypedFormControl,
UntypedFormGroup,
} from '@angular/forms'
import { By } from '@angular/platform-browser'
import { RegisterStateService } from '../../register-state.service'
import { RegisterObservabilityService } from '../../register-observability.service'

Expand All @@ -28,23 +35,30 @@ import { RegisterObservabilityService } from '../../register-observability.servi
export class MockFormCurrentEmploymentComponent
implements ControlValueAccessor
{
@Output() skipStep = new EventEmitter<void>()
writeValue(): void {}
registerOnChange(fn: () => void): void {}
registerOnTouched(fn: () => void): void {}
}

describe('StepCComponent', () => {
describe('StepC2Component', () => {
let component: StepC2Component
let fixture: ComponentFixture<StepC2Component>
let registerStateServiceStub: { registerStepperButtonClicked: jasmine.Spy }

beforeEach(() => {
registerStateServiceStub = {
registerStepperButtonClicked: jasmine.createSpy(
'registerStepperButtonClicked'
),
}
TestBed.configureTestingModule({
imports: [ReactiveFormsModule],
declarations: [StepC2Component, MockFormCurrentEmploymentComponent],
providers: [
{
provide: RegisterStateService,
useValue: {},
useValue: registerStateServiceStub,
},
{
provide: RegisterObservabilityService,
Expand All @@ -67,4 +81,46 @@ describe('StepCComponent', () => {
it('should create', () => {
expect(component).toBeTruthy()
})

it('marks the step subtitle as optional', () => {
const subtitle: HTMLElement = fixture.nativeElement.querySelector(
'mat-card-subtitle h2'
)

expect(subtitle.textContent).toContain('Step 3 of 5 - Current employment')
expect(subtitle.querySelector('em').textContent).toContain('(Optional)')
})

it('offers to skip the step and continue registration', () => {
const skipButton: HTMLElement = fixture.nativeElement.querySelector(
'#step-c2-skip-button'
)

expect(skipButton.textContent).toContain(
'Skip this step and continue registration'
)
})

it('flags the step as optional and advances when skipped', () => {
const optionalChange = jasmine.createSpy('formGroupStepC2OptionalChange')
component.formGroupStepC2OptionalChange.subscribe(optionalChange)

component.optionalNextStep()

expect(optionalChange).toHaveBeenCalledWith(true)
expect(
registerStateServiceStub.registerStepperButtonClicked
).toHaveBeenCalledWith('c2', 'skip')
})

it('skips the step when the employment form requests it', () => {
spyOn(component, 'optionalNextStep')
const employmentForm = fixture.debugElement.query(
By.directive(MockFormCurrentEmploymentComponent)
).componentInstance as MockFormCurrentEmploymentComponent

employmentForm.skipStep.emit()

expect(component.optionalNextStep).toHaveBeenCalled()
})
})
Loading
Loading