-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
FOR-469: Add word and character counter components
- Loading branch information
1 parent
c0a8d87
commit 4680291
Showing
12 changed files
with
828 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,6 +35,7 @@ node_modules | |
*~ | ||
*.sublime-project | ||
*.sublime-workspace | ||
.DS_STORE | ||
|
||
# Built javascript | ||
all.js |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{% macro hmpoCharacterCount(ctx, params, base) %} | ||
{%- from "../hmpo-text-count/macro.njk" import hmpoTextCount %} | ||
{{- hmpoTextCount(ctx, params, { | ||
type: "charactercount", | ||
classes: "govuk-!-width-three-quarters" | ||
}, base) }} | ||
{% endmacro %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,175 @@ | ||
'use strict'; | ||
|
||
describe('hmpoCharacterCount', () => { | ||
let locals; | ||
|
||
beforeEach(() => { | ||
locals = { | ||
options: { | ||
fields: { | ||
'my-input': { | ||
validate: 'required' | ||
} | ||
} | ||
}, | ||
values: { | ||
'my-input': 'abc123' | ||
} | ||
}; | ||
}); | ||
|
||
it('renders with id', () => { | ||
const $ = render({ component: 'hmpoCharacterCount', params: { id: 'my-input' }, ctx: true }, locals); | ||
const $component = $('.govuk-textarea'); | ||
|
||
expect($component.attr('id')).to.equal('my-input'); | ||
}); | ||
|
||
it('renders with label and hint', () => { | ||
const $ = render({ component: 'hmpoCharacterCount', params: { id: 'my-input' }, ctx: true }, locals); | ||
const $label = $('.govuk-label'); | ||
const $hint = $('.govuk-hint'); | ||
|
||
expect($label.text().trim()).to.equal('[fields.my-input.label]'); | ||
expect($label.attr('id')).to.equal('my-input-label'); | ||
expect($hint.text().trim()).to.equal('[fields.my-input.hint]'); | ||
}); | ||
|
||
it('does not render extra hint if there is no localisatio, but will render character count hint', () => { | ||
locals.translate = sinon.stub(); | ||
locals.translate.returnsArg(0); | ||
locals.translate.withArgs('fields.my-input.hint').returns(undefined); | ||
|
||
const $ = render({ component: 'hmpoCharacterCount', params: { id: 'my-input' }, ctx: true }, locals); | ||
const $label = $('.govuk-label'); | ||
const $hint = $('.govuk-hint'); | ||
|
||
expect($label.text().trim()).to.equal('fields.my-input.label'); | ||
expect($label.attr('id')).to.equal('my-input-label'); | ||
expect($hint.length).to.equal(1); | ||
}); | ||
|
||
it('renders with value', () => { | ||
const $ = render({ component: 'hmpoCharacterCount', params: { id: 'my-input' }, ctx: true }, locals); | ||
const $component = $('.govuk-textarea'); | ||
|
||
expect($component.text()).to.equal('abc123'); | ||
}); | ||
|
||
it('renders with aria-required=false if validator is not required', () => { | ||
locals.options.fields['my-input'].validate = undefined; | ||
|
||
const $ = render({ component: 'hmpoCharacterCount', params: { id: 'my-input' }, ctx: true }, locals); | ||
const $component = $('.govuk-textarea'); | ||
|
||
expect($component.attr('aria-required')).to.equal('false'); | ||
}); | ||
|
||
it('renders with no aria-required if validator is required', () => { | ||
const $ = render({ component: 'hmpoCharacterCount', params: { id: 'my-input' }, ctx: true }, locals); | ||
const $component = $('.govuk-textarea'); | ||
|
||
expect($component.attr('aria-required')).to.be.undefined; | ||
}); | ||
|
||
it('renders with no aria-required if validators contains required', () => { | ||
locals.options.fields['my-input'].validate = [ 'required' ]; | ||
|
||
const $ = render({ component: 'hmpoCharacterCount', params: { id: 'my-input' }, ctx: true }, locals); | ||
const $component = $('.govuk-textarea'); | ||
|
||
expect($component.attr('aria-required')).to.be.undefined; | ||
}); | ||
|
||
it('renders with no aria-required if validators contains required validator object', () => { | ||
locals.options.fields['my-input'].validate = [ { type: 'required' } ]; | ||
|
||
const $ = render({ component: 'hmpoCharacterCount', params: { id: 'my-input' }, ctx: true }, locals); | ||
const $component = $('.govuk-textarea'); | ||
|
||
expect($component.attr('aria-required')).to.be.undefined; | ||
}); | ||
|
||
it('renders with max-characters from validator', () => { | ||
const maxcharacters = 5; | ||
locals.options.fields['my-input'].validate = [ { type: 'maxlength', arguments: maxcharacters } ]; | ||
|
||
const $ = render({ component: 'hmpoCharacterCount', params: { id: 'my-input', maxlength: maxcharacters }, ctx: true }, locals); | ||
const $component = $('.govuk-character-count__message'); | ||
const countMessage = $component.text(); | ||
|
||
expect(countMessage).to.contain(maxcharacters); | ||
expect(countMessage).to.contain('characters'); | ||
}); | ||
|
||
it('renders with max-characters from validator array', () => { | ||
const maxcharacters = 5; | ||
locals.options.fields['my-input'].validate = [ { type: 'maxlength', arguments: [ maxcharacters ] } ]; | ||
|
||
const $ = render({ component: 'hmpoCharacterCount', params: { id: 'my-input', maxlength: maxcharacters }, ctx: true }, locals); | ||
const $component = $('.govuk-character-count__message'); | ||
const countMessage = $component.text(); | ||
|
||
expect(countMessage).to.contain(maxcharacters); | ||
expect(countMessage).to.contain('characters'); | ||
}); | ||
|
||
|
||
it('renders with errorValue if available', () => { | ||
locals.errorValues = { | ||
'my-input': 'def456' | ||
}; | ||
|
||
const $ = render({ component: 'hmpoCharacterCount', params: { id: 'my-input' }, ctx: true }, locals); | ||
const $component = $('.govuk-textarea'); | ||
|
||
expect($component.text()).to.equal('def456'); | ||
}); | ||
|
||
it('renders error message if available', () => { | ||
locals.errors = { | ||
'my-input': { key: 'my-input', type: 'validator' } | ||
}; | ||
|
||
const $ = render({ component: 'hmpoCharacterCount', params: { id: 'my-input' }, ctx: true }, locals); | ||
const $component = $('#my-input-error'); | ||
|
||
expect($component.text().trim()).to.equal('[govuk.error]: [fields.my-input.validation.validator]'); | ||
}); | ||
|
||
it('renders label as header', () => { | ||
const $ = render({ component: 'hmpoCharacterCount', params: { id: 'my-input', isPageHeading: true }, ctx: true }, locals); | ||
const $label = $('h1 .govuk-label'); | ||
|
||
expect($label.attr('class')).to.equal('govuk-label govuk-label--l'); | ||
}); | ||
|
||
it('renders with nopaste', () => { | ||
const $ = render({ component: 'hmpoCharacterCount', params: { id: 'my-input', isPageHeading: true, noPaste: true }, ctx: true }, locals); | ||
const $label = $('.govuk-textarea'); | ||
|
||
expect($label.attr('class')).to.equal('govuk-textarea govuk-js-character-count govuk-!-width-three-quarters js-nopaste'); | ||
}); | ||
|
||
it('renders with no extra classes', () => { | ||
const $ = render({ component: 'hmpoCharacterCount', params: { id: 'my-input', isPageHeading: true }, ctx: true }, locals); | ||
const $label = $('.govuk-textarea'); | ||
|
||
expect($label.attr('class')).to.equal('govuk-textarea govuk-js-character-count govuk-!-width-three-quarters'); | ||
}); | ||
|
||
it('renders with extra classes', () => { | ||
const $ = render({ component: 'hmpoCharacterCount', params: { id: 'my-input', isPageHeading: true, classes: 'test' }, ctx: true }, locals); | ||
const $label = $('.govuk-textarea'); | ||
|
||
expect($label.attr('class')).to.equal('govuk-textarea govuk-js-character-count test'); | ||
}); | ||
|
||
it('renders with extra classes and noPaste', () => { | ||
const $ = render({ component: 'hmpoCharacterCount', params: { id: 'my-input', isPageHeading: true, classes: 'test', noPaste: true }, ctx: true }, locals); | ||
const $label = $('.govuk-textarea'); | ||
|
||
expect($label.attr('class')).to.equal('govuk-textarea govuk-js-character-count test js-nopaste'); | ||
}); | ||
|
||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
{% macro hmpoTextCount(ctx, params, base) %} | ||
{%- set params = hmpoGetParams(ctx, params, base) %} | ||
|
||
{%- set pageHeading = { | ||
isPageHeading: true, | ||
classes: "govuk-label--l" | ||
} if params.isPageHeading %} | ||
{%- set args = { | ||
id: params.id, | ||
name: params.id, | ||
label: merge( | ||
pageHeading, | ||
{ attributes: { id: params.id + "-label" } }, | ||
hmpoGetOptions(ctx, params, "label") | ||
), | ||
spellcheck: hmpoGetOptions(ctx, params, "spellcheck", true), | ||
threshold: params.threshold, | ||
hint: hmpoGetOptions(ctx, params, "hint", true), | ||
value: hmpoGetValue(ctx, params), | ||
errorMessage: hmpoGetError(ctx, params), | ||
inputmode: params.inputmode, | ||
countMessage: params.countMessage, | ||
classes: "" + (params.classes if params.classes else "govuk-!-width-one-half") + (" js-nopaste" if params.noPaste), | ||
formGroup: params.formGroup, | ||
autocomplete: params.autocomplete, | ||
rows: params.rows, | ||
attributes: hmpoGetAttributes(ctx, params, { | ||
"aria-required": hmpoGetValidatorAttribute(ctx, params, "required", null, false) | ||
} | filter(null)) | ||
} %} | ||
|
||
{% if params.type == 'wordcount' %} | ||
|
||
{%- set args = args | add("maxwords", hmpoGetValidatorAttribute(ctx, params, "maxwords", 0)) %} | ||
{%- set wordsUnderLimitText = hmpoTranslateExtraFieldContent(ctx, params, "wordsUnderLimitText", true) %} | ||
{%- set wordsAtLimitText = hmpoTranslateExtraFieldContent(ctx, params, "wordsAtLimitText", true) %} | ||
{%- set wordsOverLimitText = hmpoTranslateExtraFieldContent(ctx, params, "wordsOverLimitText", true) %} | ||
|
||
{%- if wordsUnderLimitText != undefined %} | ||
{%- set args = args | add("wordsUnderLimitText", wordsUnderLimitText) %} | ||
{% endif %} | ||
|
||
{%- if wordsAtLimitText != undefined %} | ||
{%- set args = args | add("wordsAtLimitText", wordsAtLimitText) %} | ||
{% endif %} | ||
|
||
{%- if wordsOverLimitText != undefined %} | ||
{%- set args = args | add("wordsOverLimitText", wordsOverLimitText) %} | ||
{% endif %} | ||
|
||
{%- else %} | ||
|
||
{%- set args = args | add("maxlength", hmpoGetValidatorAttribute(ctx, params, "maxlength", 0)) %} | ||
{%- set charactersUnderLimitText = hmpoTranslateExtraFieldContent(ctx, params, "charactersUnderLimitText", true) %} | ||
{%- set charactersAtLimitText = hmpoTranslateExtraFieldContent(ctx, params, "charactersAtLimitText", true) %} | ||
{%- set charactersOverLimitText = hmpoTranslateExtraFieldContent(ctx, params, "charactersOverLimitText", true) %} | ||
|
||
{%- if charactersUnderLimitText != undefined %} | ||
{%- set args = args | add("charactersUnderLimitText", charactersUnderLimitText) %} | ||
{% endif %} | ||
|
||
{%- if charactersAtLimitText != undefined %} | ||
{%- set args = args | add("charactersAtLimitText", charactersAtLimitText) %} | ||
{% endif %} | ||
|
||
{%- if charactersOverLimitText != undefined %} | ||
{%- set args = args | add("charactersOverLimitText", charactersOverLimitText) %} | ||
{% endif %} | ||
|
||
{% endif %} | ||
|
||
{%- set textareaDescriptionText = hmpoTranslateExtraFieldContent(ctx, params, "textareaDescriptionText", true) %} | ||
{%- if textareaDescriptionText != undefined %} | ||
{%- set args = args | add("textareaDescriptionText", textareaDescriptionText) %} | ||
{% endif %} | ||
|
||
{%- from "govuk/components/character-count/macro.njk" import govukCharacterCount %} | ||
{{- govukCharacterCount(args) }} | ||
{% endmacro %} |
Oops, something went wrong.