diff --git a/__snapshots__/layout/_template.spec.js.snap b/__snapshots__/layout/_template.spec.js.snap index 59f088f549..85ee78e001 100644 --- a/__snapshots__/layout/_template.spec.js.snap +++ b/__snapshots__/layout/_template.spec.js.snap @@ -1393,13 +1393,19 @@ exports[`base page template matches the full configuration snapshot 1`] = ` + + + + + @@ -1457,13 +1468,19 @@ exports[`base page template matches the full configuration snapshot 1`] = ` + + + + + @@ -1521,13 +1543,19 @@ exports[`base page template matches the full configuration snapshot 1`] = ` + + + + + @@ -1601,13 +1633,19 @@ exports[`base page template matches the full configuration snapshot 1`] = ` + + + + + diff --git a/src/components/access-code/_macro.spec.js b/src/components/access-code/_macro.spec.js index fca3234649..f592f88704 100644 --- a/src/components/access-code/_macro.spec.js +++ b/src/components/access-code/_macro.spec.js @@ -5,150 +5,184 @@ import * as cheerio from 'cheerio'; import axe from '../../tests/helpers/axe'; import { renderComponent } from '../../tests/helpers/rendering'; -describe('macro: access-code', () => { - it('passes jest-axe checks', async () => { - const $ = cheerio.load( - renderComponent('access-code', { - id: 'example-access-code', - label: { - text: 'Enter your 16-character access code', - description: 'Keep this code safe. You will need to enter it every time you access your study', - }, - }), - ); - - const results = await axe($.html()); - expect(results).toHaveNoViolations(); +describe('FOR: access-code', () => { + describe('GIVEN: Params: required', () => { + describe('WHEN: all required params are provided', () => { + const $ = cheerio.load( + renderComponent('access-code', { + id: 'example-access-code', + label: { + text: 'Enter your 16-character access code', + description: 'Keep this code safe. You will need to enter it every time you access your study', + }, + }), + ); + test('THEN: jest-axe tests pass', async () => { + const results = await axe($.html()); + expect(results).toHaveNoViolations(); + }); + test('THEN: autocomplete is disabled on text input', () => { + expect($('input').attr('autocomplete')).toBe('off'); + }); + test('THEN: text input has automatic capitalisation', () => { + expect($('input').attr('autocapitalize')).toBe('characters'); + }); + }); }); - - it('has the provided `id` attribute', () => { - const $ = cheerio.load( - renderComponent('access-code', { - id: 'example-id', - }), - ); - - expect($('#example-id').length).toBe(1); + describe('GIVEN: Params: id', () => { + describe('WHEN: id is provided', () => { + const $ = cheerio.load( + renderComponent('access-code', { + id: 'example-id', + }), + ); + test('THEN: renders with id provided', () => { + expect($('#example-id').length).toBe(1); + }); + }); }); - - it('has the provided `name` attribute', () => { - const $ = cheerio.load( - renderComponent('access-code', { - name: 'special-name', - }), - ); - - expect($('input').attr('name')).toBe('special-name'); + describe('GIVEN: Params: classes', () => { + describe('WHEN: additional style classes are provided', () => { + const $ = cheerio.load( + renderComponent('access-code', { + classes: 'extra-class another-extra-class', + }), + ); + test('THEN: renders with additional classes provided', () => { + expect($('.ons-panel--info').hasClass('extra-class')).toBe(true); + expect($('.ons-panel--info').hasClass('another-extra-class')).toBe(true); + }); + }); }); - - it('has a default `type` of "text"', () => { - const $ = cheerio.load(renderComponent('access-code')); - - expect($('input').attr('type')).toBe('text'); + describe('GIVEN: Params: label', () => { + describe('WHEN: label text and description params are provided', () => { + const $ = cheerio.load( + renderComponent('access-code', { + label: { + text: 'Enter your 16-character access code', + description: 'Keep this code safe. You will need to enter it every time you access your study', + }, + }), + ); + test('THEN: renders with provided text and description', () => { + expect($('.ons-label--with-description').text()).toBe('Enter your 16-character access code'); + expect($('.ons-input--with-description').text()).toBe( + 'Keep this code safe. You will need to enter it every time you access your study', + ); + }); + }); }); - - it('has the provided `type` attribute', () => { - const $ = cheerio.load( - renderComponent('access-code', { - type: 'number', - }), - ); - - expect($('input').attr('inputmode')).toBe('numeric'); + describe('GIVEN: Params: type', () => { + describe('WHEN: param is at default state', () => { + const $ = cheerio.load(renderComponent('access-code')); + test('THEN: renders with default type of "text"', () => { + expect($('input').attr('type')).toBe('text'); + }); + }); + describe('WHEN: type param is provided', () => { + const $ = cheerio.load( + renderComponent('access-code', { + type: 'number', + }), + ); + test('THEN: renders with provided type', () => { + expect($('input').attr('inputmode')).toBe('numeric'); + }); + }); }); - - it('has additionally provided style classes', () => { - const $ = cheerio.load( - renderComponent('access-code', { - classes: 'extra-class another-extra-class', - }), - ); - - expect($('.ons-panel--info').hasClass('extra-class')).toBe(true); - expect($('.ons-panel--info').hasClass('another-extra-class')).toBe(true); + describe('GIVEN: Params: name', () => { + describe('WHEN: name param is provided', () => { + const $ = cheerio.load( + renderComponent('access-code', { + name: 'special-name', + }), + ); + test('THEN: renders with provided name', () => { + expect($('input').attr('name')).toBe('special-name'); + }); + }); }); - - it('has provided label text and description', () => { - const $ = cheerio.load( - renderComponent('access-code', { - label: { - text: 'Enter your 16-character access code', - description: 'Keep this code safe. You will need to enter it every time you access your study', - }, - }), - ); - - expect($('.ons-label--with-description').text()).toBe('Enter your 16-character access code'); - expect($('.ons-input--with-description').text()).toBe( - 'Keep this code safe. You will need to enter it every time you access your study', - ); + describe('GIVEN: Params: maxlength & groupSize', () => { + describe('WHEN: params are at default state', () => { + const $ = cheerio.load(renderComponent('access-code')); + test('THEN: renders input with total maxlength of 19', () => { + expect($('input').attr('maxlength')).toBe('19'); + }); + test('THEN: renders input with groupSize of 4', () => { + expect($('input').attr('data-group-size')).toBe('4'); + }); + }); + describe('WHEN: maxlength param is provided', () => { + const $ = cheerio.load( + renderComponent('access-code', { + maxlength: 8, + }), + ); + test('THEN: renders input with provided maxlength', () => { + expect($('input').attr('maxlength')).toBe('9'); + }); + }); + describe('WHEN: groupSize param is provided', () => { + const $ = cheerio.load( + renderComponent('access-code', { + groupSize: 2, + }), + ); + test('THEN: renders input with provided groupSize', () => { + expect($('input').attr('data-group-size')).toBe('2'); + }); + }); + describe('WHEN: maxlength and groupSize params are provided', () => { + const $ = cheerio.load( + renderComponent('access-code', { + maxlength: 6, + groupSize: 3, + }), + ); + test('THEN: renders input with provided maxlength accounting for provided groupSize', () => { + expect($('input').attr('maxlength')).toBe('7'); + }); + }); }); - - it('has provided maximum length attribute including spaces required for groupSize', () => { - const $ = cheerio.load( - renderComponent('access-code', { - maxlength: 6, - groupSize: 3, - }), - ); - - expect($('input').attr('maxlength')).toBe('7'); + describe('GIVEN: Params: securityMessage', () => { + describe('WHEN: securityMessage param is provided', () => { + const $ = cheerio.load( + renderComponent('access-code', { + securityMessage: 'Example security message.', + }), + ); + test('THEN: renders with provided security message', () => { + expect($('.ons-panel__body').text().trim()).toBe('Example security message.'); + }); + }); }); - - it('has provided group size attribute', () => { - const $ = cheerio.load( - renderComponent('access-code', { - groupSize: 2, - }), - ); - - expect($('input').attr('data-group-size')).toBe('2'); - }); - - it('has autocomplete disabled on its text input', () => { - const $ = cheerio.load(renderComponent('access-code')); - - expect($('input').attr('autocomplete')).toBe('off'); + describe('GIVEN: Params: postTextboxLinkText & postTextBoxLinkUrl', () => { + describe('WHEN: postTextboxLinkText & postTextBoxLinkUrl params are provided', () => { + const $ = cheerio.load( + renderComponent('access-code', { + postTextboxLinkText: 'Example link text', + postTextboxLinkUrl: '#3', + }), + ); + test('THEN: renders link with provided link and text', () => { + expect($('a[href="#3"]').text().trim()).toBe('Example link text'); + }); + }); }); - - it('has automatic capitalization on its text input', () => { - const $ = cheerio.load(renderComponent('access-code')); - - expect($('input').attr('autocapitalize')).toBe('characters'); - }); - - it('has provided security message text', () => { - const $ = cheerio.load( - renderComponent('access-code', { - securityMessage: 'Example security message.', - }), - ); - - expect($('.ons-panel__body').text().trim()).toBe('Example security message.'); - }); - - it('has provided `postTextBoxLinkText` and `postTextBoxLinkUrl`', () => { - const $ = cheerio.load( - renderComponent('access-code', { - postTextboxLinkText: 'Example link text', - postTextboxLinkUrl: '#3', - }), - ); - - expect($('a[href="#3"]').text().trim()).toBe('Example link text'); - }); - - it('has provided `error` output', () => { - const $ = cheerio.load( - renderComponent('access-code', { - error: { - id: 'access-code-error', - text: 'Enter an access code', - }, - }), - ); - - expect($('#access-code-error').length).toBe(1); - expect($('.ons-panel__error > strong').text()).toBe('Enter an access code'); + describe('GIVEN: Params: error', () => { + describe('WHEN: error id & text params are provided', () => { + const $ = cheerio.load( + renderComponent('access-code', { + error: { + id: 'access-code-error', + text: 'Enter an access code', + }, + }), + ); + test('THEN: renders error with provided id and text', () => { + expect($('#access-code-error').length).toBe(1); + expect($('.ons-panel__error > strong').text()).toBe('Enter an access code'); + }); + }); }); }); diff --git a/src/components/back-to-top/_macro.spec.js b/src/components/back-to-top/_macro.spec.js index b44be197ed..a8ac0b81eb 100644 --- a/src/components/back-to-top/_macro.spec.js +++ b/src/components/back-to-top/_macro.spec.js @@ -5,56 +5,50 @@ import * as cheerio from 'cheerio'; import axe from '../../tests/helpers/axe'; import { renderComponent } from '../../tests/helpers/rendering'; -describe('macro: back-to-top', () => { - it('passes jest-axe checks', async () => { - const $ = cheerio.load( - renderComponent('back-to-top', { - description: 'Back to top', - anchor: 'example-target', - }), - ); - - const results = await axe($.html()); - expect(results).toHaveNoViolations(); - }); - - it('has back to top link with the provided description', async () => { - const $ = cheerio.load( - renderComponent('back-to-top', { - description: 'Scroll to top', - anchor: 'example-target', - }), - ); - expect($('.ons-back-to-top .ons-back-to-top__link').text().trim()).toBe('Scroll to top'); - }); - - it('has back to top link with the provided anchor', async () => { - const $ = cheerio.load( - renderComponent('back-to-top', { - description: 'Back to top', - anchor: 'example-target', - }), - ); - - expect($('.ons-back-to-top .ons-back-to-top__link').attr('href')).toBe('#example-target'); +describe('FOR: Back-to-top', () => { + describe('GIVEN: Params: default', () => { + describe('WHEN: params are at default', () => { + const $ = cheerio.load(renderComponent('back-to-top')); + test('THEN: jest-axe tests pass', async () => { + const results = await axe($.html()); + expect(results).toHaveNoViolations(); + }); + }); }); - - it('has back to top link with the default description if no description provided', async () => { - const $ = cheerio.load( - renderComponent('back-to-top', { - anchor: 'example-target', - }), - ); - - expect($('.ons-back-to-top .ons-back-to-top__link').text().trim()).toBe('Back to top'); + describe('GIVEN: Params: description', () => { + describe('WHEN: description text is not provided', () => { + const $ = cheerio.load(renderComponent('back-to-top')); + test('THEN: renders with default description text', () => { + expect($('.ons-back-to-top .ons-back-to-top__link').text().trim()).toBe('Back to top'); + }); + }); + describe('WHEN: description text is provided', () => { + const $ = cheerio.load( + renderComponent('back-to-top', { + description: 'Scroll to top', + }), + ); + test('THEN: renders button with provided text', () => { + expect($('.ons-back-to-top .ons-back-to-top__link').text().trim()).toBe('Scroll to top'); + }); + }); }); - - it('has back to top link with the default anchor if no anchor provided', async () => { - const renderedComponent = renderComponent('back-to-top', { - description: 'Back to top', + describe('GIVEN: Params: anchor', () => { + describe('WHEN: anchor is not provided', () => { + const $ = cheerio.load(renderComponent('back-to-top')); + test('THEN: renders with default anchor id', () => { + expect($('.ons-back-to-top .ons-back-to-top__link').attr('href')).toBe('#top'); + }); + }); + describe('WHEN: anchor is provided', () => { + const $ = cheerio.load( + renderComponent('back-to-top', { + anchor: 'example-target', + }), + ); + test('THEN: renders button with provided anchor id', () => { + expect($('.ons-back-to-top .ons-back-to-top__link').attr('href')).toBe('#example-target'); + }); }); - const $ = cheerio.load(renderedComponent); - - expect($('.ons-back-to-top .ons-back-to-top__link').attr('href')).toBe('#top'); }); }); diff --git a/src/components/list/_macro.njk b/src/components/list/_macro.njk index 4beabec2f6..775777e282 100644 --- a/src/components/list/_macro.njk +++ b/src/components/list/_macro.njk @@ -20,10 +20,17 @@ {% else %} {% set listEl = 'ul' %} {% endif %} + + {% if listLength < 2 %} + {% set attributes = params.itemsList[0].attributes %} + {% else %} + {% set attributes = params.attributes %} + {% endif %} {% set openingTag = "<" + listEl %} {% set closingTag = "" %} + {{ openingTag | safe }}{% if params.id %}{{ ' ' }}id="{{ params.id }}"{% endif %} - class="ons-list{{ ' ons-list--p' if listEl == 'p' }}{{ ' ' + params.classes if params.classes else '' }}{% if params.variants %}{% if params.variants is not string %}{% for variant in variants %}{{ ' ' }}ons-list--{{ variant }}{% endfor %}{% else %}{{ ' ' }}ons-list--{{ variants }}{% endif %}{% endif %}{{ ' ' + otherClasses if otherClasses else '' }}"{% if params.attributes %}{% for attribute, value in (params.attributes.items() if params.attributes is mapping and params.attributes.items else params.attributes) %}{{ ' ' }}{{ attribute }}{% if value %}="{{ value }}"{% endif %}{% endfor %}{% endif %}> + class="ons-list{{ ' ons-list--p' if listEl == 'p' }}{{ ' ' + params.classes if params.classes else '' }}{% if params.variants %}{% if params.variants is not string %}{% for variant in variants %}{{ ' ' }}ons-list--{{ variant }}{% endfor %}{% else %}{{ ' ' }}ons-list--{{ variants }}{% endif %}{% endif %}{{ ' ' + otherClasses if otherClasses else '' }}"{% if params.attributes or params.itemsList[0].attributes %}{% for attribute, value in (attributes.items() if attributes is mapping and attributes.items else attributes) %}{{ ' ' }}{{ attribute }}{% if value %}="{{ value }}"{% endif %}{% endfor %}{% endif %}> {%- for item in params.itemsList -%} {% set sublistClasses = item.listClasses if item.listClasses %} {% @@ -74,6 +81,7 @@ }) }} {%- else -%} + {# Remove setting attributes on link in future update #} 1 or listEl == 'ul' %} + {# Remove if not item.url in future update #}
  • {{- listItem | safe -}}