Skip to content
This repository has been archived by the owner on Dec 8, 2022. It is now read-only.

Added a11y attributes for text expand #1959

Merged
merged 6 commits into from
Sep 6, 2018
Merged
Show file tree
Hide file tree
Changes from 2 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
@@ -1,10 +1,13 @@
import { Component } from '@angular/core';
import { Component, ViewChild } from '@angular/core';
import { SkyTextExpandRepeaterComponent } from '../text-expand-repeater.component';

@Component({
selector: 'sky-text-expand-repeater-demo',
templateUrl: './text-expand-repeater.component.fixture.html'
})
export class TextExpandRepeaterTestComponent {
@ViewChild(SkyTextExpandRepeaterComponent)
public textExpand: SkyTextExpandRepeaterComponent;
public data: string[];
public numItems: number;
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
<div class="sky-text-expand-repeater">
<ul class="sky-text-expand-repeater-container" (transitionend)="animationEnd()" #container>
<ul class="sky-text-expand-repeater-container" [id]="contentSectionId" (transitionend)="animationEnd()" #container>
<li *ngFor="let item of contentItems" class="sky-text-expand-repeater-item">
{{item}}
</li>
</ul>
<button type="button" class="sky-btn sky-btn-link-inline sky-text-expand-repeater-see-more" *ngIf="expandable" (click)="repeaterExpand()">
<button *ngIf="expandable"
type="button"
class="sky-btn sky-btn-link-inline sky-text-expand-repeater-see-more"
[attr.aria-expanded]="isExpanded"
[attr.aria-controls]="contentSectionId"
(click)="repeaterExpand()"
>
{{buttonText}}
</button>
</div>
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import {
TestBed,
async
async,
fakeAsync,
tick
} from '@angular/core/testing';

import { BrowserModule } from '@angular/platform-browser';
Expand All @@ -24,6 +26,31 @@ describe('Text expand repeater component', () => {
});

describe('basic behaviors', () => {
it('should have necessary aria properties', fakeAsync(() => {
let fixture = TestBed.createComponent(TextExpandRepeaterTestComponent);
let cmp = fixture.componentInstance as TextExpandRepeaterTestComponent;
let el = fixture.nativeElement as HTMLElement;

cmp.data = ['john', 'bob', 'hank'];
cmp.numItems = 2;

fixture.detectChanges();
const buttonElem = <HTMLElement>el.querySelector('.sky-text-expand-repeater-see-more');

expect(buttonElem.getAttribute('aria-expanded')).toBe('false');
expect(buttonElem.getAttribute('aria-controls')).toBe(cmp.textExpand.contentSectionId);

buttonElem.click();
fixture.detectChanges();
tick(20);
fixture.detectChanges();
tick(500);
fixture.detectChanges();

expect(buttonElem.getAttribute('aria-expanded')).toBe('true');
expect(buttonElem.getAttribute('aria-controls')).toBe(cmp.textExpand.contentSectionId);
}));

it('should not have see more button if data is less than or equal to max items', () => {
let fixture = TestBed.createComponent(TextExpandRepeaterTestComponent);
let cmp = fixture.componentInstance as TextExpandRepeaterTestComponent;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ import {
import {
SkyResourcesService
} from '../resources';

/**
* Auto-incrementing integer used to generate unique ids for checkbox components.
Blackbaud-TrevorBurch marked this conversation as resolved.
Show resolved Hide resolved
*/
let nextId = 0;

@Component({
selector: 'sky-text-expand-repeater',
templateUrl: './text-expand-repeater.component.html',
Expand All @@ -30,6 +36,7 @@ export class SkyTextExpandRepeaterComponent implements AfterViewInit {
public buttonText: string;
public contentItems: Array<any>;
public expandable: boolean;
public contentSectionId: string = `sky-text-expand-repeater-content-${++nextId}`;

private seeMoreText: string = this.resources.getString('text_expand_see_more');
private seeLessText: string = this.resources.getString('text_expand_see_less');
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { Component } from '@angular/core';
import { Component, ViewChild } from '@angular/core';
import { SkyTextExpandComponent } from '../text-expand.component';

@Component({
selector: 'sky-text-expand-demo',
templateUrl: './text-expand.component.fixture.html'
})
export class TextExpandTestComponent {
// tslint:disable-next-line

@ViewChild(SkyTextExpandComponent)
public textExpand: SkyTextExpandComponent;
public text: string;
public maxLength: number;
public truncateNewlines: boolean = true;
Expand Down
13 changes: 11 additions & 2 deletions src/modules/text-expand/text-expand.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,16 @@
class="sky-text-expand-container"
(transitionend)="animationEnd()"
#container>
<span class="sky-text-expand-text" #text></span>
<span class="sky-text-expand-text" [id]="contentSectionId" #text></span>
<span class="sky-text-expand-ellipsis" *ngIf="!isExpanded && expandable">... </span>
<button type="button" class="sky-btn sky-btn-link-inline sky-text-expand-see-more" *ngIf="expandable" (click)="textExpand()">{{buttonText}}</button>
<button *ngIf="expandable"
type="button"
class="sky-btn sky-btn-link-inline sky-text-expand-see-more"
[attr.aria-expanded]="isModal ? undefined : isExpanded"
[attr.aria-controls]="isModal ? undefined : contentSectionId"
[attr.aria-haspopup]="isModal ? 'dialog' : undefined"
(click)="textExpand()"
>
{{buttonText}}
</button>
</div>
100 changes: 67 additions & 33 deletions src/modules/text-expand/text-expand.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import {
TestBed,
inject,
async
fakeAsync,
tick
} from '@angular/core/testing';

import { BrowserModule } from '@angular/platform-browser';
Expand Down Expand Up @@ -63,6 +64,42 @@ describe('Text expand component', () => {
);

describe('basic behaviors', () => {

it('should have necessary aria properties', fakeAsync(() => {
let fixture = TestBed.createComponent(TextExpandTestComponent);
let cmp = fixture.componentInstance as TextExpandTestComponent;
let el = fixture.nativeElement as HTMLElement;

// tslint:disable-next-line
cmp.text = 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec.';
Blackbaud-TrevorBurch marked this conversation as resolved.
Show resolved Hide resolved

fixture.detectChanges();
const buttonElem = <HTMLElement>el.querySelector('.sky-text-expand-see-more');

expect(buttonElem.getAttribute('aria-expanded')).toBe('false');
expect(buttonElem.getAttribute('aria-controls')).toBe(cmp.textExpand.contentSectionId);
expect(buttonElem.getAttribute('aria-haspopup')).toBeNull();

buttonElem.click();
fixture.detectChanges();
tick(20);
fixture.detectChanges();
tick(500);
fixture.detectChanges();

expect(buttonElem.getAttribute('aria-expanded')).toBe('true');
expect(buttonElem.getAttribute('aria-controls')).toBe(cmp.textExpand.contentSectionId);
expect(buttonElem.getAttribute('aria-haspopup')).toBeNull();

// tslint:disable-next-line
cmp.text = 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies';
fixture.detectChanges();

expect(buttonElem.getAttribute('aria-expanded')).toBeNull();
expect(buttonElem.getAttribute('aria-controls')).toBeNull();
expect(buttonElem.getAttribute('aria-haspopup')).toBe('dialog');
}));

it('should not have see more button or ellipsis if text is short', () => {
let fixture = TestBed.createComponent(TextExpandTestComponent);
let cmp = fixture.componentInstance as TextExpandTestComponent;
Expand Down Expand Up @@ -231,7 +268,7 @@ describe('Text expand component', () => {
expect(seeMoreButton.innerText.trim()).toBe(SkyResources.getString('text_expand_see_more'));
});

it('should expand on click of the see more button', async(() => {
it('should expand on click of the see more button', fakeAsync(() => {
Blackbaud-TrevorBurch marked this conversation as resolved.
Show resolved Hide resolved
let fixture = TestBed.createComponent(TextExpandTestComponent);
let cmp = fixture.componentInstance as TextExpandTestComponent;
let el = fixture.nativeElement as HTMLElement;
Expand All @@ -253,37 +290,34 @@ describe('Text expand component', () => {

seeMoreButton.click();
fixture.detectChanges();
Blackbaud-TrevorBurch marked this conversation as resolved.
Show resolved Hide resolved
fixture.whenStable().then(() => {
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
ellipsis = el.querySelector('.sky-text-expand-ellipsis');
textArea = <HTMLElement>el.querySelector('.sky-text-expand-text');

expect(container.style.maxHeight).toBe('');
expect(seeMoreButton.innerText.trim())
.toBe(SkyResources.getString('text_expand_see_less'));
expect(ellipsis).toBeNull();
expect(textArea.innerText.trim()).toBe(expandedText);
seeMoreButton.click();
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
ellipsis = el.querySelector('.sky-text-expand-ellipsis');
textArea = <HTMLElement>el.querySelector('.sky-text-expand-text');

expect(container.style.maxHeight).toBe('');
expect(seeMoreButton.innerText.trim())
.toBe(SkyResources.getString('text_expand_see_more'));
expect(ellipsis).not.toBeNull();
expect(textArea.innerText.trim()).toBe(collapsedText);
});
});
});
});
}), 300000);
tick(20);
fixture.detectChanges();
tick(500);
fixture.detectChanges();
ellipsis = el.querySelector('.sky-text-expand-ellipsis');
textArea = <HTMLElement>el.querySelector('.sky-text-expand-text');

expect(container.style.maxHeight).toBe('');
expect(seeMoreButton.innerText.trim())
.toBe(SkyResources.getString('text_expand_see_less'));
expect(ellipsis).toBeNull();
expect(textArea.innerText.trim()).toBe(expandedText);
seeMoreButton.click();
fixture.detectChanges();
tick(20);
fixture.detectChanges();
tick(500);
fixture.detectChanges();
ellipsis = el.querySelector('.sky-text-expand-ellipsis');
textArea = <HTMLElement>el.querySelector('.sky-text-expand-text');

expect(container.style.maxHeight).toBe('');
expect(seeMoreButton.innerText.trim())
.toBe(SkyResources.getString('text_expand_see_more'));
expect(ellipsis).not.toBeNull();
expect(textArea.innerText.trim()).toBe(collapsedText);

}));

it('should render newlines if requested', () => {
let fixture = TestBed.createComponent(TextExpandTestComponent);
Expand Down
13 changes: 11 additions & 2 deletions src/modules/text-expand/text-expand.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ import {
SkyTextExpandAdapterService
} from './text-expand-adapter.service';

/**
* Auto-incrementing integer used to generate unique ids for checkbox components.
Blackbaud-TrevorBurch marked this conversation as resolved.
Show resolved Hide resolved
*/
let nextId = 0;

@Component({
selector: 'sky-text-expand',
templateUrl: './text-expand.component.html',
Expand Down Expand Up @@ -61,6 +66,9 @@ export class SkyTextExpandComponent implements AfterContentInit {
public isExpanded: boolean = false;
public expandable: boolean;
public buttonText: string;
public contentSectionId: string = `sky-text-expand-content-${++nextId}`;
public isModal: boolean;

private seeMoreText: string = this.resources.getString('text_expand_see_more');
private seeLessText: string = this.resources.getString('text_expand_see_less');
private textToShow: string;
Expand All @@ -74,8 +82,7 @@ export class SkyTextExpandComponent implements AfterContentInit {
private textExpandAdapter: SkyTextExpandAdapterService) { }

public textExpand() {
if (this.newlineCount > this.maxExpandedNewlines
|| this.expandedText.length > this.maxExpandedLength) {
if (this.isModal) {
// Modal View
/* istanbul ignore else */
/* sanity check */
Expand Down Expand Up @@ -143,6 +150,8 @@ export class SkyTextExpandComponent implements AfterContentInit {
this.buttonText = this.seeMoreText;
this.isExpanded = false;
this.expandable = true;
this.isModal = this.newlineCount > this.maxExpandedNewlines
|| this.expandedText.length > this.maxExpandedLength;
} else {
this.expandable = false;
}
Expand Down