-
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 character and word count components
* Update git ignore to ignore ds_store * Add hmpo-text-counter as base for new word and character counter; it implements gds character counter * Add hmpo-word-counter to count words, based on hmpo-text-counter * Add hmpo-character-counter to count characters, based on hmpo-text-counter * Add unit tests for each component * Add new global function to translate extra field keys * Add unit test for new global function * Update README with new components * Add globals to dev dependency * Add uglify step in prepare script
- Loading branch information
1 parent
bf69b2f
commit 2886838
Showing
14 changed files
with
832 additions
and
8 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,167 @@ | ||
'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'); | ||
expect($label.text().trim()).to.equal('[fields.my-input.label]'); | ||
expect($label.attr('id')).to.equal('my-input-label'); | ||
const $hint = $('.govuk-hint'); | ||
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'); | ||
expect($label.text().trim()).to.equal('fields.my-input.label'); | ||
expect($label.attr('id')).to.equal('my-input-label'); | ||
const $hint = $('.govuk-hint'); | ||
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
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.