@ons/design-system 55.2.0 → 56.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/button/_button.scss +48 -50
- package/components/button/_macro.njk +45 -19
- package/components/button/_macro.spec.js +24 -24
- package/components/button/button.spec.js +11 -11
- package/components/fieldset/_fieldset.scss +5 -0
- package/components/footer/_macro.njk +2 -6
- package/components/footer/_macro.spec.js +0 -6
- package/components/header/_macro.njk +6 -8
- package/components/header/_macro.spec.js +4 -8
- package/components/input/_macro.njk +1 -0
- package/components/input/_macro.spec.js +2 -0
- package/components/modal/_macro.njk +1 -0
- package/components/modal/modal.js +33 -0
- package/components/modal/modal.spec.js +76 -0
- package/components/navigation/_macro.njk +3 -2
- package/components/navigation/_macro.spec.js +3 -2
- package/components/question/_macro.njk +2 -2
- package/components/question/_macro.spec.js +2 -2
- package/components/question/_question.scss +1 -1
- package/components/relationships/_macro.njk +2 -1
- package/components/search/_macro.njk +12 -2
- package/components/search/_macro.spec.js +27 -2
- package/components/summary/_macro.njk +23 -29
- package/components/summary/_macro.spec.js +38 -38
- package/components/summary/_summary.scss +41 -10
- package/components/timeout-modal/_macro.njk +1 -0
- package/components/timeout-modal/timeout-modal.js +1 -1
- package/components/timeout-modal/timeout-modal.spec.js +68 -0
- package/css/census.css +1 -1
- package/css/ids.css +1 -1
- package/css/main.css +1 -1
- package/package.json +1 -1
- package/scripts/main.es5.js +1 -1
- package/scripts/main.js +1 -1
- package/scss/patternlib.scss +2 -2
|
@@ -41,6 +41,7 @@ const EXAMPLE_WITH_SEARCH = {
|
|
|
41
41
|
attributes: { a: 42 },
|
|
42
42
|
classes: 'extra-search-button-class',
|
|
43
43
|
iconType: 'search',
|
|
44
|
+
visuallyHideButtonText: true,
|
|
44
45
|
},
|
|
45
46
|
};
|
|
46
47
|
|
|
@@ -540,6 +541,7 @@ describe('macro: input', () => {
|
|
|
540
541
|
attributes: { a: 42 },
|
|
541
542
|
classes: 'extra-search-button-class',
|
|
542
543
|
iconType: 'search',
|
|
544
|
+
visuallyHideButtonText: true,
|
|
543
545
|
},
|
|
544
546
|
});
|
|
545
547
|
});
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
role="dialog"
|
|
6
6
|
aria-labelledby="ons-modal-title"
|
|
7
7
|
{% if params.attributes %}{% for attribute, value in (params.attributes.items() if params.attributes is mapping and params.attributes.items else params.attributes) %} {{attribute}}="{{value}}"{% endfor %}{% endif %}
|
|
8
|
+
{% if params.enableGA == true %}data-enable-ga='true'{% endif %}
|
|
8
9
|
>
|
|
9
10
|
<div class="ons-modal__content">
|
|
10
11
|
<h2 id="ons-modal-title" class="ons-modal__title">
|
|
@@ -8,8 +8,11 @@ export default class Modal {
|
|
|
8
8
|
this.component = component;
|
|
9
9
|
this.launcher = document.querySelector(`[data-modal-id=${component.id}]`);
|
|
10
10
|
this.closeButton = component.querySelector('.ons-js-modal-btn');
|
|
11
|
+
this.setGaAttributes = component.getAttribute('data-enable-ga');
|
|
11
12
|
this.lastFocusedEl = null;
|
|
12
13
|
this.dialogCSSSupported = true;
|
|
14
|
+
this.modalType = this.component.classList.contains('ons-js-timeout-modal') ? 'Timeout' : 'Generic';
|
|
15
|
+
|
|
13
16
|
this.initialise();
|
|
14
17
|
}
|
|
15
18
|
|
|
@@ -26,6 +29,10 @@ export default class Modal {
|
|
|
26
29
|
if (this.closeButton) {
|
|
27
30
|
this.closeButton.addEventListener('click', this.closeDialog.bind(this));
|
|
28
31
|
}
|
|
32
|
+
|
|
33
|
+
if (this.modalType !== 'Timeout') {
|
|
34
|
+
window.addEventListener('keydown', this.escToClose.bind(this));
|
|
35
|
+
}
|
|
29
36
|
}
|
|
30
37
|
|
|
31
38
|
dialogSupported() {
|
|
@@ -60,6 +67,16 @@ export default class Modal {
|
|
|
60
67
|
} else {
|
|
61
68
|
this.component.showModal();
|
|
62
69
|
}
|
|
70
|
+
|
|
71
|
+
if (this.setGaAttributes) {
|
|
72
|
+
if (event) {
|
|
73
|
+
this.component.setAttribute('data-ga-action', `Modal opened by ${event.type} event`);
|
|
74
|
+
} else {
|
|
75
|
+
this.component.setAttribute('data-ga-action', 'Modal opened by timed event');
|
|
76
|
+
}
|
|
77
|
+
this.component.setAttribute('data-ga-label', `${this.modalType} modal opened`);
|
|
78
|
+
this.component.setAttribute('data-ga-category', `${this.modalType} modal`);
|
|
79
|
+
}
|
|
63
80
|
}
|
|
64
81
|
}
|
|
65
82
|
|
|
@@ -96,6 +113,22 @@ export default class Modal {
|
|
|
96
113
|
|
|
97
114
|
this.component.close();
|
|
98
115
|
this.setFocusOnLastFocusedEl(this.lastFocusedEl);
|
|
116
|
+
|
|
117
|
+
if (this.setGaAttributes) {
|
|
118
|
+
if (event) {
|
|
119
|
+
this.component.setAttribute('data-ga-action', `Modal closed by ${event.type} event`);
|
|
120
|
+
} else {
|
|
121
|
+
this.component.setAttribute('data-ga-action', 'Modal closed by timed event');
|
|
122
|
+
}
|
|
123
|
+
this.component.setAttribute('data-ga-label', `${this.modalType} modal closed`);
|
|
124
|
+
this.component.setAttribute('data-ga-category', `${this.modalType} modal`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
escToClose(event) {
|
|
130
|
+
if (this.isDialogOpen() && event.keyCode === 27) {
|
|
131
|
+
this.closeDialog(event);
|
|
99
132
|
}
|
|
100
133
|
}
|
|
101
134
|
}
|
|
@@ -55,5 +55,81 @@ describe('script: modal', () => {
|
|
|
55
55
|
expect(activeElementId).toBe('launcher');
|
|
56
56
|
});
|
|
57
57
|
});
|
|
58
|
+
|
|
59
|
+
describe('when the `esc` key is pressed', () => {
|
|
60
|
+
beforeEach(async () => {
|
|
61
|
+
await page.focus('.ons-js-modal-btn');
|
|
62
|
+
await page.keyboard.press('Enter');
|
|
63
|
+
await page.keyboard.press('Escape');
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('closes the modal', async () => {
|
|
67
|
+
const modalIsVisible = await page.$eval('.ons-modal', node => node.classList.contains('ons-u-db'));
|
|
68
|
+
expect(modalIsVisible).toBe(false);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
describe('when GA tracking is enabled', () => {
|
|
74
|
+
beforeEach(async () => {
|
|
75
|
+
const component = renderComponent('modal', { ...EXAMPLE_MODAL, enableGA: true });
|
|
76
|
+
const template = `
|
|
77
|
+
<div class="ons-page">
|
|
78
|
+
<button id="launcher" data-modal-id="dialog">Launcher</button>
|
|
79
|
+
${component}
|
|
80
|
+
</div>
|
|
81
|
+
`;
|
|
82
|
+
await setTestPage('/test', template);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
describe('when the modal is launched by a click event', () => {
|
|
86
|
+
beforeEach(async () => {
|
|
87
|
+
await page.focus('#launcher');
|
|
88
|
+
await page.keyboard.press('Enter');
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('has the correct attributes set on the modal', async () => {
|
|
92
|
+
const gaLabel = await page.$eval('.ons-modal', node => node.getAttribute('data-ga-label'));
|
|
93
|
+
const gaAction = await page.$eval('.ons-modal', node => node.getAttribute('data-ga-action'));
|
|
94
|
+
const gaCategory = await page.$eval('.ons-modal', node => node.getAttribute('data-ga-category'));
|
|
95
|
+
expect(gaLabel).toBe('Generic modal opened');
|
|
96
|
+
expect(gaAction).toBe('Modal opened by click event');
|
|
97
|
+
expect(gaCategory).toBe('Generic modal');
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
describe('when the modal is closed by a click event', () => {
|
|
102
|
+
beforeEach(async () => {
|
|
103
|
+
await page.focus('#launcher');
|
|
104
|
+
await page.keyboard.press('Enter');
|
|
105
|
+
await page.click('.ons-js-modal-btn');
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('has the correct attributes set on the modal', async () => {
|
|
109
|
+
const gaLabel = await page.$eval('.ons-modal', node => node.getAttribute('data-ga-label'));
|
|
110
|
+
const gaAction = await page.$eval('.ons-modal', node => node.getAttribute('data-ga-action'));
|
|
111
|
+
const gaCategory = await page.$eval('.ons-modal', node => node.getAttribute('data-ga-category'));
|
|
112
|
+
expect(gaLabel).toBe('Generic modal closed');
|
|
113
|
+
expect(gaAction).toBe('Modal closed by click event');
|
|
114
|
+
expect(gaCategory).toBe('Generic modal');
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
describe('when the modal is closed by `escape` keypress event', () => {
|
|
119
|
+
beforeEach(async () => {
|
|
120
|
+
await page.focus('#launcher');
|
|
121
|
+
await page.keyboard.press('Enter');
|
|
122
|
+
await page.keyboard.press('Escape');
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('has the correct attributes set on the modal', async () => {
|
|
126
|
+
const gaLabel = await page.$eval('.ons-modal', node => node.getAttribute('data-ga-label'));
|
|
127
|
+
const gaAction = await page.$eval('.ons-modal', node => node.getAttribute('data-ga-action'));
|
|
128
|
+
const gaCategory = await page.$eval('.ons-modal', node => node.getAttribute('data-ga-category'));
|
|
129
|
+
expect(gaLabel).toBe('Generic modal closed');
|
|
130
|
+
expect(gaAction).toBe('Modal closed by keydown event');
|
|
131
|
+
expect(gaCategory).toBe('Generic modal');
|
|
132
|
+
});
|
|
133
|
+
});
|
|
58
134
|
});
|
|
59
135
|
});
|
|
@@ -64,8 +64,9 @@
|
|
|
64
64
|
<div class="ons-u-d-no@l{{ ' ' + params.navigation.subNavigation.classes if params.navigation.subNavigation.classes }}">
|
|
65
65
|
{{ onsButton({
|
|
66
66
|
"text": params.navigation.currentPageTitle,
|
|
67
|
-
"classes": "ons-u-d-no ons-js-sub-navigation-button
|
|
68
|
-
"
|
|
67
|
+
"classes": "ons-u-d-no ons-js-sub-navigation-button",
|
|
68
|
+
"type": "button",
|
|
69
|
+
"variants": ["mobile", "dropdown"],
|
|
69
70
|
"attributes": {
|
|
70
71
|
"aria-label": "Toggle section navigation",
|
|
71
72
|
"aria-controls": params.navigation.subNavigation.id,
|
|
@@ -206,8 +206,9 @@ describe('macro: navigation', () => {
|
|
|
206
206
|
|
|
207
207
|
expect(buttonSpy.occurrences).toContainEqual({
|
|
208
208
|
text: 'Main nav item 2',
|
|
209
|
-
classes: 'ons-u-d-no ons-js-sub-navigation-button
|
|
210
|
-
|
|
209
|
+
classes: 'ons-u-d-no ons-js-sub-navigation-button',
|
|
210
|
+
variants: ['mobile', 'dropdown'],
|
|
211
|
+
type: 'button',
|
|
211
212
|
attributes: {
|
|
212
213
|
'aria-label': 'Toggle section navigation',
|
|
213
214
|
'aria-controls': 'sub-nav',
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
{% if params.legendIsQuestionTitle %}
|
|
69
69
|
{% from "components/fieldset/_macro.njk" import onsFieldset %}
|
|
70
70
|
|
|
71
|
-
{# Resolves caller issue in
|
|
71
|
+
{# Resolves caller issue in Jinja: https://github.com/pallets/jinja/issues/371 #}
|
|
72
72
|
{% set content = caller() if caller %}
|
|
73
73
|
<div class="ons-question__answer ons-u-mb-m">
|
|
74
74
|
{% call onsFieldset({
|
|
@@ -125,7 +125,7 @@
|
|
|
125
125
|
{{
|
|
126
126
|
onsButton({
|
|
127
127
|
"id": params.submitButton.id,
|
|
128
|
-
"
|
|
128
|
+
"variants": params.submitButton.variants,
|
|
129
129
|
"text": params.submitButton.text | default ('Save and continue'),
|
|
130
130
|
"classes": params.submitButton.classes,
|
|
131
131
|
"attributes": params.submitButton.attributes
|
|
@@ -47,7 +47,7 @@ const EXAMPLE_QUESTION_BUTTON = {
|
|
|
47
47
|
...EXAMPLE_QUESTION_BASIC,
|
|
48
48
|
submitButton: {
|
|
49
49
|
id: 'button-id',
|
|
50
|
-
|
|
50
|
+
variants: 'timer',
|
|
51
51
|
text: 'Button text',
|
|
52
52
|
},
|
|
53
53
|
};
|
|
@@ -252,7 +252,7 @@ describe('macro: question', () => {
|
|
|
252
252
|
|
|
253
253
|
faker.renderComponent('question', EXAMPLE_QUESTION_BUTTON);
|
|
254
254
|
|
|
255
|
-
expect(buttonSpy.occurrences[0]).toHaveProperty('
|
|
255
|
+
expect(buttonSpy.occurrences[0]).toHaveProperty('variants', 'timer');
|
|
256
256
|
expect(buttonSpy.occurrences[0]).toHaveProperty('id', 'button-id');
|
|
257
257
|
expect(buttonSpy.occurrences[0]).toHaveProperty('text', 'Button text');
|
|
258
258
|
});
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
"name": params.name,
|
|
10
10
|
"dontWrap": params.dontWrap,
|
|
11
11
|
"legendIsQuestionTitle": params.legendIsQuestionTitle,
|
|
12
|
-
"radios": params.radios
|
|
12
|
+
"radios": params.radios,
|
|
13
|
+
"error": params.error
|
|
13
14
|
}) }}
|
|
14
15
|
<p class="ons-relationships__playback ons-js-relationships-playback ons-u-d-no" aria-live="polite">{{ params.playback | safe }}</p>
|
|
15
16
|
</div>
|
|
@@ -5,15 +5,25 @@
|
|
|
5
5
|
|
|
6
6
|
<div class="ons-search-component">
|
|
7
7
|
{{ content | safe }}
|
|
8
|
+
|
|
9
|
+
{%- set buttonLabel -%}
|
|
10
|
+
{%- if params.searchButton.visuallyHideButtonText == true -%}
|
|
11
|
+
<span class="ons-u-vh">{{ params.searchButton.text }}</span>
|
|
12
|
+
{%- else -%}
|
|
13
|
+
{{ params.searchButton.text }}
|
|
14
|
+
{%- endif -%}
|
|
15
|
+
{%- endset -%}
|
|
16
|
+
|
|
8
17
|
{{
|
|
9
18
|
onsButton({
|
|
10
19
|
"type": params.searchButton.type,
|
|
11
|
-
"
|
|
20
|
+
"html": buttonLabel,
|
|
12
21
|
"id": params.searchButton.id,
|
|
13
22
|
"variants": 'small',
|
|
14
23
|
"classes": 'ons-search__btn ons-u-mt-xs@xxs@s' + (" " + params.searchButton.classes if params.searchButton.classes else ""),
|
|
15
24
|
"attributes": params.searchButton.attributes,
|
|
16
|
-
"iconType": params.searchButton.iconType
|
|
25
|
+
"iconType": params.searchButton.iconType,
|
|
26
|
+
"iconPosition": 'only' if params.searchButton.visuallyHideButtonText == true else 'before'
|
|
17
27
|
})
|
|
18
28
|
}}
|
|
19
29
|
</div>
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import * as cheerio from 'cheerio';
|
|
4
4
|
|
|
5
|
-
import axe from '../../tests/helpers/axe';
|
|
6
5
|
import { renderComponent, templateFaker } from '../../tests/helpers/rendering';
|
|
7
6
|
|
|
8
7
|
const EXAMPLE_SEARCH = {
|
|
@@ -34,11 +33,37 @@ describe('macro: search', () => {
|
|
|
34
33
|
expect(buttonSpy.occurrences[0]).toEqual({
|
|
35
34
|
id: 'search-button-id',
|
|
36
35
|
type: 'button',
|
|
37
|
-
|
|
36
|
+
html: 'Search for address',
|
|
38
37
|
variants: 'small',
|
|
39
38
|
classes: 'ons-search__btn ons-u-mt-xs@xxs@s extra-search-button-class',
|
|
40
39
|
attributes: EXAMPLE_SEARCH.searchButton.attributes,
|
|
41
40
|
iconType: 'search',
|
|
41
|
+
iconPosition: 'before',
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('renders button component with a visibly hidden label when specified', () => {
|
|
46
|
+
const faker = templateFaker();
|
|
47
|
+
const buttonSpy = faker.spy('button');
|
|
48
|
+
|
|
49
|
+
faker.renderComponent('input', {
|
|
50
|
+
searchButton: {
|
|
51
|
+
id: 'search-button-id',
|
|
52
|
+
type: 'button',
|
|
53
|
+
text: 'Search for address',
|
|
54
|
+
iconType: 'search',
|
|
55
|
+
visuallyHideButtonText: true,
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
expect(buttonSpy.occurrences[0]).toEqual({
|
|
60
|
+
id: 'search-button-id',
|
|
61
|
+
type: 'button',
|
|
62
|
+
html: '<span class="ons-u-vh">Search for address</span>',
|
|
63
|
+
variants: 'small',
|
|
64
|
+
classes: 'ons-search__btn ons-u-mt-xs@xxs@s',
|
|
65
|
+
iconPosition: 'only',
|
|
66
|
+
iconType: 'search',
|
|
42
67
|
});
|
|
43
68
|
});
|
|
44
69
|
});
|
|
@@ -20,37 +20,30 @@
|
|
|
20
20
|
{% if group.groupTitle %}
|
|
21
21
|
<h{{ titleSize }} class="ons-summary__group-title">{{ group.groupTitle }}</h{{ titleSize }}>
|
|
22
22
|
{% endif %}
|
|
23
|
-
{% if group.
|
|
24
|
-
<
|
|
25
|
-
<thead class="ons-u-vh">
|
|
26
|
-
<tr>
|
|
27
|
-
{% for header in group.headers %}
|
|
28
|
-
<th>{{ header }}</th>
|
|
29
|
-
{% endfor %}
|
|
30
|
-
</tr>
|
|
31
|
-
</thead>
|
|
23
|
+
{% if group.rows %}
|
|
24
|
+
<div class="ons-summary__items">
|
|
32
25
|
|
|
33
26
|
{% for row in (group.rows if group.rows is iterable else group.rows.items()) %}
|
|
34
27
|
{% set itemClass = "" %}
|
|
35
28
|
{% if row.error %} {% set itemClass = " ons-summary__item--error" %}{% endif %}
|
|
36
29
|
{% if row.total %} {% set itemClass = itemClass + " ons-summary__item--total" %}{% endif %}
|
|
37
30
|
|
|
38
|
-
<
|
|
39
|
-
{% if row.errorMessage
|
|
40
|
-
<
|
|
41
|
-
|
|
42
|
-
|
|
31
|
+
<div {% if row.id %}id="{{ row.id }}" {% endif %}class="ons-summary__item{{ itemClass }}">
|
|
32
|
+
{% if row.errorMessage %}
|
|
33
|
+
<div class="ons-summary__row-title--error ons-u-fs-r">{{ row.errorMessage }}</div>
|
|
34
|
+
{% endif %}
|
|
35
|
+
{% if row.rowItems | length > 1 and row.rowTitle %}
|
|
36
|
+
<div class="ons-summary__row-title ons-summary__row-title--no-group-title ons-u-fs-r">{{ row.rowTitle }}</div>
|
|
43
37
|
{% endif %}
|
|
44
38
|
|
|
45
39
|
{% for rowItem in row.rowItems %}
|
|
46
|
-
<
|
|
47
|
-
<
|
|
48
|
-
class="ons-summary__item-title"
|
|
40
|
+
<dl class="ons-summary__row{{ " ons-summary__row--has-values" if rowItem.valueList else "" }}"{% if rowItem.id %} id="{{ rowItem.id }}"{% endif %}>
|
|
41
|
+
<dt class="ons-summary__item-title{% if not rowItem.actions %} ons-summary__item-title--2{% endif %}"
|
|
49
42
|
{% if rowItem.rowTitleAttributes %}{% for attribute, value in (rowItem.rowTitleAttributes.items() if rowItem.rowTitleAttributes is mapping and rowItem.rowTitleAttributes.items else rowItem.rowTitleAttributes) %}{{attribute}}="{{value}}" {% endfor %}{% endif %}
|
|
50
43
|
>
|
|
51
44
|
{% if rowItem.iconType %}
|
|
52
45
|
{% from "components/icons/_macro.njk" import onsIcon %}
|
|
53
|
-
<span class="ons-summary__item-title-icon
|
|
46
|
+
<span class="ons-summary__item-title-icon{% if rowItem.iconType == 'check' %} ons-summary__item-title-icon--check{% endif %}">
|
|
54
47
|
{{
|
|
55
48
|
onsIcon({
|
|
56
49
|
"iconType": rowItem.iconType
|
|
@@ -59,17 +52,18 @@
|
|
|
59
52
|
</span>
|
|
60
53
|
{% endif %}
|
|
61
54
|
|
|
62
|
-
<div class="ons-summary__item--text{{ ' ons-summary__item-title--text' if rowItem.iconType else "" }}">
|
|
55
|
+
<div class="ons-summary__item--text{{ ' ons-summary__item-title--text' if rowItem.iconType else "" }}">
|
|
56
|
+
{{- rowItem.rowTitle | default(row.rowTitle) | safe -}}
|
|
57
|
+
</div>
|
|
63
58
|
|
|
64
59
|
{# Render section status for mobile if is hub #}
|
|
65
60
|
{% if params.hub and rowItem.valueList %}
|
|
66
|
-
<span class="ons-u-d-no@
|
|
61
|
+
<span class="ons-u-d-no@m ons-u-fs-r"> — {{ rowItem.valueList[0].text | safe }}</span>
|
|
67
62
|
{% endif %}
|
|
68
|
-
</
|
|
63
|
+
</dt>
|
|
69
64
|
{% if rowItem.valueList %}
|
|
70
|
-
<
|
|
65
|
+
<dd
|
|
71
66
|
class="ons-summary__values"
|
|
72
|
-
{% if rowItem.actions == null %} colspan="2"{% endif %}
|
|
73
67
|
{% if rowItem.attributes %}{% for attribute, value in (rowItem.attributes.items() if rowItem.attributes is mapping and rowItem.attributes.items else rowItem.attributes) %}{{attribute}}="{{value}}" {% endfor %}{% endif %}
|
|
74
68
|
>
|
|
75
69
|
{% if rowItem.valueList | length == 1 %}
|
|
@@ -93,10 +87,10 @@
|
|
|
93
87
|
{% endfor %}
|
|
94
88
|
</ul>
|
|
95
89
|
{% endif %}
|
|
96
|
-
</
|
|
90
|
+
</dd>
|
|
97
91
|
{% endif %}
|
|
98
92
|
{% if rowItem.actions %}
|
|
99
|
-
<
|
|
93
|
+
<dd class="ons-summary__actions">
|
|
100
94
|
{% for action in (rowItem.actions if rowItem.actions is iterable else rowItem.actions.items()) %}
|
|
101
95
|
{% if loop.index > 1 %}<span class="ons-summary__spacer"></span>{% endif %}
|
|
102
96
|
<a
|
|
@@ -106,13 +100,13 @@
|
|
|
106
100
|
{% if action.attributes %}{% for attribute, value in (action.attributes.items() if action.attributes is mapping and action.attributes.items else action.attributes) %}{{attribute}}="{{value}}" {% endfor %}{% endif %}
|
|
107
101
|
>{{ action.text }}</a>
|
|
108
102
|
{% endfor %}
|
|
109
|
-
</
|
|
103
|
+
</dd>
|
|
110
104
|
{% endif %}
|
|
111
|
-
</
|
|
105
|
+
</dl>
|
|
112
106
|
{% endfor %}
|
|
113
|
-
</
|
|
107
|
+
</div>
|
|
114
108
|
{% endfor %}
|
|
115
|
-
</
|
|
109
|
+
</div>
|
|
116
110
|
{% elif group.placeholderText %}
|
|
117
111
|
<span class="ons-summary__placeholder">{{ group.placeholderText }}</span>
|
|
118
112
|
{% endif %}
|
|
@@ -203,36 +203,28 @@ describe('macro: summary', () => {
|
|
|
203
203
|
});
|
|
204
204
|
|
|
205
205
|
describe('part: row', () => {
|
|
206
|
-
it('has the `headers` values displayed in th elements', () => {
|
|
207
|
-
const $ = cheerio.load(renderComponent('summary', EXAMPLE_SUMMARY_BASIC));
|
|
208
|
-
|
|
209
|
-
expect($('.ons-summary__items thead tr th:nth-child(1)').text()).toBe('Header 1');
|
|
210
|
-
expect($('.ons-summary__items thead tr th:nth-child(2)').text()).toBe('Header 2');
|
|
211
|
-
expect($('.ons-summary__items thead tr th:nth-child(3)').text()).toBe('Header 3');
|
|
212
|
-
});
|
|
213
|
-
|
|
214
206
|
it('has the correct row class when `error` is `true`', () => {
|
|
215
207
|
const $ = cheerio.load(renderComponent('summary', EXAMPLE_SUMMARY_BASIC));
|
|
216
208
|
|
|
217
|
-
expect($('.ons-summary__items
|
|
209
|
+
expect($('.ons-summary__items .ons-summary__item:nth-of-type(2)').hasClass('ons-summary__item--error')).toBe(true);
|
|
218
210
|
});
|
|
219
211
|
|
|
220
212
|
it('has the correct row class when `total` is `true`', () => {
|
|
221
213
|
const $ = cheerio.load(renderComponent('summary', EXAMPLE_SUMMARY_BASIC));
|
|
222
214
|
|
|
223
|
-
expect($('.ons-summary__items
|
|
215
|
+
expect($('.ons-summary__items .ons-summary__item:nth-of-type(4)').hasClass('ons-summary__item--total')).toBe(true);
|
|
224
216
|
});
|
|
225
217
|
|
|
226
218
|
it('displays the `rowTitle` text', () => {
|
|
227
219
|
const $ = cheerio.load(renderComponent('summary', EXAMPLE_SUMMARY_BASIC));
|
|
228
220
|
|
|
229
|
-
expect($('.ons-summary__items
|
|
221
|
+
expect($('.ons-summary__items .ons-summary__item:nth-of-type(3) .ons-summary__row-title').text()).toBe('row title 3');
|
|
230
222
|
});
|
|
231
223
|
|
|
232
224
|
it('overrides the `rowTitle` with the `errorMessage` if provided', () => {
|
|
233
225
|
const $ = cheerio.load(renderComponent('summary', EXAMPLE_SUMMARY_WITH_TITLE));
|
|
234
226
|
|
|
235
|
-
expect($('.ons-summary__items
|
|
227
|
+
expect($('.ons-summary__items .ons-summary__item:nth-of-type(2) .ons-summary__row-title--error').text()).toBe('there are errors');
|
|
236
228
|
});
|
|
237
229
|
|
|
238
230
|
it('has the correct row `id` for each row', () => {
|
|
@@ -262,7 +254,7 @@ describe('macro: summary', () => {
|
|
|
262
254
|
const $ = cheerio.load(renderComponent('summary', EXAMPLE_SUMMARY_BASIC));
|
|
263
255
|
|
|
264
256
|
expect(
|
|
265
|
-
$('.ons-summary__items
|
|
257
|
+
$('.ons-summary__items .ons-summary__item:nth-of-type(1) .ons-summary__item--text')
|
|
266
258
|
.text()
|
|
267
259
|
.trim(),
|
|
268
260
|
).toBe('row title 1');
|
|
@@ -289,12 +281,6 @@ describe('macro: summary', () => {
|
|
|
289
281
|
expect($('.ons-summary__item--text').hasClass('ons-summary__item-title--text')).toBe(true);
|
|
290
282
|
});
|
|
291
283
|
|
|
292
|
-
it('has a colspan attribute on the values td if there are no `actions`', () => {
|
|
293
|
-
const $ = cheerio.load(renderComponent('summary', EXAMPLE_SUMMARY_BASIC));
|
|
294
|
-
|
|
295
|
-
expect($('.ons-summary__items tbody:nth-of-type(1) .ons-summary__values').attr('colspan')).toBe('2');
|
|
296
|
-
});
|
|
297
|
-
|
|
298
284
|
it('has custom `attributes`', () => {
|
|
299
285
|
const $ = cheerio.load(renderComponent('summary', EXAMPLE_SUMMARY_BASIC));
|
|
300
286
|
|
|
@@ -308,7 +294,7 @@ describe('macro: summary', () => {
|
|
|
308
294
|
const $ = cheerio.load(renderComponent('summary', EXAMPLE_SUMMARY_BASIC));
|
|
309
295
|
|
|
310
296
|
expect(
|
|
311
|
-
$('.ons-summary__items
|
|
297
|
+
$('.ons-summary__items .ons-summary__item:nth-of-type(1) dl .ons-summary__values .ons-summary__text')
|
|
312
298
|
.text()
|
|
313
299
|
.trim(),
|
|
314
300
|
).toBe('row value 1');
|
|
@@ -318,7 +304,7 @@ describe('macro: summary', () => {
|
|
|
318
304
|
const $ = cheerio.load(renderComponent('summary', EXAMPLE_SUMMARY_BASIC));
|
|
319
305
|
|
|
320
306
|
expect(
|
|
321
|
-
$('.ons-summary__items
|
|
307
|
+
$('.ons-summary__items .ons-summary__item:nth-of-type(1) dl .ons-summary__values ul li')
|
|
322
308
|
.text()
|
|
323
309
|
.trim(),
|
|
324
310
|
).toBe('other value');
|
|
@@ -327,7 +313,7 @@ describe('macro: summary', () => {
|
|
|
327
313
|
it('wraps the `valueList` in a ul if multiple values provided', () => {
|
|
328
314
|
const $ = cheerio.load(renderComponent('summary', EXAMPLE_SUMMARY_BASIC));
|
|
329
315
|
|
|
330
|
-
expect($('.ons-summary__items
|
|
316
|
+
expect($('.ons-summary__items .ons-summary__item:nth-of-type(3) .ons-summary__values ul').length).toBe(1);
|
|
331
317
|
});
|
|
332
318
|
});
|
|
333
319
|
|
|
@@ -335,43 +321,55 @@ describe('macro: summary', () => {
|
|
|
335
321
|
it('has a spacer element if multiple actions are provided', () => {
|
|
336
322
|
const $ = cheerio.load(renderComponent('summary', EXAMPLE_SUMMARY_BASIC));
|
|
337
323
|
|
|
338
|
-
expect($('.ons-summary__items
|
|
324
|
+
expect($('.ons-summary__items .ons-summary__item:nth-of-type(2) .ons-summary__actions .ons-summary__spacer').length).toBe(1);
|
|
339
325
|
});
|
|
340
326
|
|
|
341
327
|
it('has the correct `url` for each action provided', () => {
|
|
342
328
|
const $ = cheerio.load(renderComponent('summary', EXAMPLE_SUMMARY_BASIC));
|
|
343
329
|
|
|
344
|
-
expect(
|
|
345
|
-
'
|
|
346
|
-
);
|
|
347
|
-
expect(
|
|
330
|
+
expect(
|
|
331
|
+
$('.ons-summary__items .ons-summary__item:nth-of-type(2) .ons-summary__actions .ons-summary__button:first-child').attr('href'),
|
|
332
|
+
).toBe('#1');
|
|
333
|
+
expect(
|
|
334
|
+
$('.ons-summary__items .ons-summary__item:nth-of-type(2) .ons-summary__actions .ons-summary__button:last-child').attr('href'),
|
|
335
|
+
).toBe('#2');
|
|
348
336
|
});
|
|
349
337
|
|
|
350
338
|
it('has the action `text` for each action provided', () => {
|
|
351
339
|
const $ = cheerio.load(renderComponent('summary', EXAMPLE_SUMMARY_BASIC));
|
|
352
340
|
|
|
353
|
-
expect(
|
|
354
|
-
'
|
|
355
|
-
);
|
|
356
|
-
expect(
|
|
341
|
+
expect(
|
|
342
|
+
$('.ons-summary__items .ons-summary__item:nth-of-type(2) .ons-summary__actions .ons-summary__button:first-child').text(),
|
|
343
|
+
).toBe('Action 1');
|
|
344
|
+
expect(
|
|
345
|
+
$('.ons-summary__items .ons-summary__item:nth-of-type(2) .ons-summary__actions .ons-summary__button:last-child').text(),
|
|
346
|
+
).toBe('Action 2');
|
|
357
347
|
});
|
|
358
348
|
|
|
359
349
|
it('has the `aria-label` provided', () => {
|
|
360
350
|
const $ = cheerio.load(renderComponent('summary', EXAMPLE_SUMMARY_BASIC));
|
|
361
351
|
|
|
362
352
|
expect(
|
|
363
|
-
$('.ons-summary__items
|
|
353
|
+
$('.ons-summary__items .ons-summary__item:nth-of-type(2) .ons-summary__actions .ons-summary__button:first-child').attr(
|
|
354
|
+
'aria-label',
|
|
355
|
+
),
|
|
364
356
|
).toBe('action aria label 1');
|
|
365
|
-
expect(
|
|
366
|
-
'
|
|
367
|
-
|
|
357
|
+
expect(
|
|
358
|
+
$('.ons-summary__items .ons-summary__item:nth-of-type(2) .ons-summary__actions .ons-summary__button:last-child').attr(
|
|
359
|
+
'aria-label',
|
|
360
|
+
),
|
|
361
|
+
).toBe('action aria label 2');
|
|
368
362
|
});
|
|
369
363
|
|
|
370
364
|
it('has custom `attributes`', () => {
|
|
371
365
|
const $ = cheerio.load(renderComponent('summary', EXAMPLE_SUMMARY_BASIC));
|
|
372
366
|
|
|
373
|
-
expect(
|
|
374
|
-
|
|
367
|
+
expect(
|
|
368
|
+
$('.ons-summary__items .ons-summary__item:nth-of-type(2) .ons-summary__actions .ons-summary__button:first-child').attr('a'),
|
|
369
|
+
).toBe('abc');
|
|
370
|
+
expect(
|
|
371
|
+
$('.ons-summary__items .ons-summary__item:nth-of-type(2) .ons-summary__actions .ons-summary__button:first-child').attr('b'),
|
|
372
|
+
).toBe('def');
|
|
375
373
|
});
|
|
376
374
|
});
|
|
377
375
|
});
|
|
@@ -423,7 +421,9 @@ describe('macro: summary', () => {
|
|
|
423
421
|
}),
|
|
424
422
|
);
|
|
425
423
|
|
|
426
|
-
expect($('.ons-summary__items
|
|
424
|
+
expect($('.ons-summary__items .ons-summary__item:nth-of-type(2) .ons-summary__row .ons-summary__item-title span').text()).toBe(
|
|
425
|
+
' — row value 2',
|
|
426
|
+
);
|
|
427
427
|
});
|
|
428
428
|
});
|
|
429
429
|
|