Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DC-26939-hashTrigger-function-fix #379

Merged
merged 5 commits into from
Dec 9, 2021
Merged
Show file tree
Hide file tree
Changes from all 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
46 changes: 46 additions & 0 deletions e2e/__tests__/components/accordion-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
const puppeteer = require('puppeteer');
const ct = require('../../config/constants');
let browser;
let page;

beforeAll(async () => {
browser = await puppeteer.launch({headless: true, args: ['--no-sandbox', '--disable-setuid-sandbox']});
page = await browser.newPage();
await page.setViewport({ width: ct.BT_XL, height: ct.WH });
});

describe('SWE Components testing', () => {
test('Accordion is working as expected', async () => {
await page.goto(`${ct.APP_URL}/docs/components/accordion.html`, { waitUntil: 'networkidle0' });
// 1. -> accordion exist on the page
await page.waitForSelector('.qg-accordion-v2');

// 2. -> check all the collapsing-sections are closed on page load
expect(await page.evaluate('$(\'.collapsing-section\').css(\'display\')')).toBe('none');

// 3. -> click on a accordion heading and check collapsing section visibility changes
await page.click('.acc-heading');
expect(await page.evaluate('$(\'.collapsing-section\').css(\'display\')')).not.toBe('none');

// 4. -> click on collapse all button and check collapsing section visibility changes
await page.click('.controls.collapse');
await page.waitForTimeout(1000);
expect(await page.evaluate('$(\'.collapsing-section\').css(\'display\')')).toBe('none');

// 5. -> click on expand all button and check collapsing section visibility changes
await page.click('.controls.expand');
await page.waitForTimeout(1000);
expect(await page.evaluate('$(\'.collapsing-section\').css(\'display\')')).not.toBe('none');

// 6. -> check hashtrigger function by inserting a heading on the URL (#with-icon) and check that particular accordion panel open
await page.click('.controls.collapse');
await page.goto(`${ct.APP_URL}/docs/components/accordion.html#with-icon`, { waitUntil: 'networkidle0' });
await page.reload({ waitUntil: ['networkidle0', 'domcontentloaded'] });
await page.waitForTimeout(1000);
expect(await page.evaluate('$(".title:contains(\'With icon\')").parents(\'article\').find(\'.collapsing-section\').css(\'display\');')).not.toBe('none');
});

afterAll(async () => {
await browser.close();
});
});
4 changes: 2 additions & 2 deletions e2e/__tests__/components/funnelback-search-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ beforeAll(async () => {

describe('SWE Header testing', () => {
test('Funnelback search is working as expected', async () => {
expect(await page.evaluate('window.getComputedStyle(document.querySelector(\'.qg-search-concierge-initial\')).getPropertyValue("visibility")')).toBe('hidden');
expect(await page.evaluate('$(\'.qg-search-concierge-initial\').css(\'visibility\')')).toBe('hidden');
await page.click('input#qg-search-query');
await page.waitForTimeout(ct.WT);
expect(await page.evaluate('window.getComputedStyle(document.querySelector(\'.qg-search-concierge-initial\')).getPropertyValue("visibility")')).toBe('visible');
expect(await page.evaluate('$(\'.qg-search-concierge-initial\').css(\'visibility\')')).toBe('visible');
await page.type('#qg-search-query', 'jobs', { delay: 20 });
await page.waitForTimeout(ct.WT);
const element = await page.$('.qg-search-concierge-content li button');
Expand Down
313 changes: 155 additions & 158 deletions src/assets/_project/_blocks/components/accordion/qg-accordion.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,177 +4,174 @@
* - Ability to direct link to each section and expand the linked section
* - Handles aria-expanded values
*/
export class QgAccordion {
constructor () {
this.$accordion = $('.qg-accordion');
this.$accordion_v2 = $('.qg-accordion-v2');
this.$accHeading = $('.acc-heading');

(function ($) {
var qgAccordion = {
config: {
$accordion: $('.qg-accordion'),
// qg-accordion-v2 adds accessibility enhancement to the exiting accordion. The reason for creating a new selector is to maintain backward compatibility with the existing accordion (swe2 accordion).
$accordion_v2: $('.qg-accordion-v2'),
$accHeading: $('.acc-heading'),
},
if (this.$accordion.length > 0) {
this.accordionPanelClick();
this.collapseAll();
this.expandAll();
this.hashTrigger();
// enable GA tracking
this.gaTracking();
// legacyAccordion is to support SWE2 accordion
this.legacyAccordion();
}
}

/**
* Initialise qgAccordion
* @return {undefined}
**/
init: function() {
if (this.config.$accordion.length > 0) {
this.accordionClick();
this.collapseAll();
this.expandAll();
this.hashTrigger();
// enable GA tracking
this.gaTracking();
// legacyAccordion is to support SWE2 accordion
this.legacyAccordion();
}
},
/**
* filterSpecialChar
* @param {string} value - value to filter
* @return {undefined}
**/
filterSpecialChar(value){
return decodeURI(value.toLowerCase().replace(/[^a-zA-Z0-9/]/g, ''));
}

urlHash: function (){
return decodeURI(window.location.hash.replace(/\/|#|{|}|\+|\\/g, ''));
},
/**
* hashTrigger function open matching accordion if it finds #title-Of-Accordion in the url
* function trims down the hash value, and then it matches with the titles of the accordion, and if there is a matching title, then it open that panel
* @return {undefined}
**/
hashTrigger(){
let self = this;
let hashValTrimmed = this.filterSpecialChar(window.location.hash);
if (hashValTrimmed.length > 0) {
self.$accordion.find('.title').each(function (index, titleEl){
if (self.filterSpecialChar($(titleEl).text()) === hashValTrimmed){
$(this).parents(self.$accHeading).trigger('click');
}
});
}
}

/**
* hashTrigger function open matching accordion if it finds #title-Of-Accordion in the url
* @return {undefined}
**/
// TODO check hashTrigger function looks like not working
hashTrigger: function (){
let hashVal = this.urlHash();
if (hashVal.length > 0) {
let findHashVal = this.config.$accordion.find('#' + hashVal + '');
findHashVal.click();
findHashVal.parent('article').find('.acc-heading').focus();
}
},
/**
* toggleOpenCloseClass function toggle the class and 'aria-expanded' value according to the accordion state
* @param {selector} curr - target selector
* @return {undefined}
**/
toggleOpenCloseClass(curr){
if (curr.hasClass('qg-accordion--open')){
curr.removeClass('qg-accordion--open').addClass('qg-accordion--closed');
curr.attr('aria-expanded', 'false');
} else {
curr.removeClass('qg-accordion--closed').addClass('qg-accordion--open');
curr.attr('aria-expanded', 'true');
}
}

/**
* toggleOpenCloseClass function toggle the class and 'aria-expanded' value according to the accordion state
* @param {selector} curr - target selector
* @return {undefined}
**/
toggleOpenCloseClass: function(curr){
if (curr.hasClass('qg-accordion--open')){
curr.removeClass('qg-accordion--open').addClass('qg-accordion--closed');
curr.attr('aria-expanded', 'false');
} else {
curr.removeClass('qg-accordion--closed').addClass('qg-accordion--open');
curr.attr('aria-expanded', 'true');
}
},
/**
* accordionClick -> click on an accordion
* @return {undefined}
**/
accordionPanelClick(){
let self = this;
let accHeading = self.$accordion_v2.find(self.$accHeading);
accHeading.on('click', function (event) {
self.toggleOpenCloseClass($(this));
});
}

/**
* accordionClick -> click on an accordion
* @return {undefined}
**/
accordionClick: function(){
let self = this;
let accHeading = this.config.$accordion_v2.find(this.config.$accHeading);
accHeading.on('click', function (event) {
self.toggleOpenCloseClass($(this));
});
},

/**
* keyboardAccessibility -> accordion to work with keyboard
* @param {string} event -> click , keypress etc
* @return {undefined}
**/
keyboardAccessibility: function (event){
if (event.type === 'click') {
/**
* keyboardAccessibility -> accordion to work with keyboard
* @param {string} event -> click , keypress etc
* @return {undefined}
**/
keyboardAccessibility(event){
if (event.type === 'click') {
return true;
} else if (event.type === 'keypress') {
var code = event.charCode || event.keyCode;
if ((code === 32) || (code === 13)) {
return true;
} else if (event.type === 'keypress') {
var code = event.charCode || event.keyCode;
if ((code === 32) || (code === 13)) {
return true;
}
} else {
return false;
}
},
} else {
return false;
}
}

/**
* collapseAll -> collapse all accordion on a page on clicking 'Collapse all' button
* @return {undefined}
**/
collapseAll: function (){
var self = this;
// collapse all click
// label selector is to provide backward compatibility in case projects are using old markup
$('.qg-acc-controls .collapse, label[for=\'collapse\']').on('click keypress', function (event) {
if (self.keyboardAccessibility(event) === true) {
$(this).parents('.qg-accordion').find('.acc-heading').removeClass('qg-accordion--open').addClass('qg-accordion--closed');
// backward compatible code to support SWE2 accordion
$(this).parents('.qg-accordion').find('input:checkbox').prop('checked', false);
event.preventDefault();
}
});
},
/**
* collapseAll -> collapse all accordion on a page on clicking 'Collapse all' button
* @return {undefined}
**/
collapseAll(){
let self = this;
// collapse all click
// label selector is to provide backward compatibility in case projects are using old markup
$('.qg-acc-controls .collapse, label[for=\'collapse\']').on('click keypress', function (event) {
if (self.keyboardAccessibility(event) === true) {
$(this).parents('.qg-accordion').find('.acc-heading').removeClass('qg-accordion--open').addClass('qg-accordion--closed');
// backward compatible code to support SWE2 accordion
$(this).parents('.qg-accordion').find('input:checkbox').prop('checked', false);
event.preventDefault();
}
});
}

/**
* expandAll -> expand all accordion on a page on clicking 'Expand all' button
* @return {undefined}
**/
expandAll: function (){
var self = this;
//expand all click
// label selector is to provide backward compatibility in case projects are using old markup
$('.qg-acc-controls .expand, label[for=\'expand\']').on('click keypress', function (event) {
if (self.keyboardAccessibility(event) === true) {
$(this).parents('.qg-accordion').find('.acc-heading').removeClass('qg-accordion--closed').addClass('qg-accordion--open');
// backward compatible code to support SWE2 accordion
$(this).parents('.qg-accordion').find('input:checkbox').prop('checked', true);
event.preventDefault();
}
});
},
/**
* expandAll -> expand all accordion on a page on clicking 'Expand all' button
* @return {undefined}
**/
expandAll(){
let self = this;
//expand all click
// label selector is to provide backward compatibility in case projects are using old markup
$('.qg-acc-controls .expand, label[for=\'expand\']').on('click keypress', function (event) {
if (self.keyboardAccessibility(event) === true) {
$(this).parents('.qg-accordion').find('.acc-heading').removeClass('qg-accordion--closed').addClass('qg-accordion--open');
// backward compatible code to support SWE2 accordion
$(this).parents('.qg-accordion').find('input:checkbox').prop('checked', true);
event.preventDefault();
}
});
}

/**
* gaTracking -> enable tracking on accordion, this function adds an attribute 'data-analytics-link-group' with a acc title
* @return {undefined}
**/
gaTracking: function(){
this.config.$accordion.find('.qg-accordion--ga').each(function(){
let title = 'accordion title - ' + $(this).find($('.title')).text();
$(this).attr('data-analytics-link-group', title);
});
},
/**
* gaTracking -> enable tracking on accordion, this function adds an attribute 'data-analytics-link-group' with a acc title
* @return {undefined}
**/
gaTracking(){
this.$accordion.find('.qg-accordion--ga').each(function(){
let title = 'accordion title - ' + $(this).find($('.title')).text();
$(this).attr('data-analytics-link-group', title);
});
}

/**
* legacyAccordion function supports swe2 accordion in use at some places
* @return {undefined}
**/
legacyAccordion: function (){
let self = this;
let accItem = $('.qg-accordion:not(.qg-accordion-v2)').find('article');
accItem.find('.acc-heading').on('keypress', function (event) {
if (event.target === event.currentTarget) {
event.preventDefault();
if (self.keyboardAccessibility(event) === true) {
let parent = $(this).parent();
if (parent.find('input[name="tabs"]:checked').length > 0) {
parent.find('input[name="tabs"]').prop('checked', false);
} else {
parent.find('input[name="tabs"]').prop('checked', true);
}
/**
* legacyAccordion function supports swe2 accordion in use at some places
* @return {undefined}
**/
legacyAccordion(){
let self = this;
let accItem = $('.qg-accordion:not(.qg-accordion-v2)').find('article');
accItem.find('.acc-heading').on('keypress', function (event) {
if (event.target === event.currentTarget) {
event.preventDefault();
if (self.keyboardAccessibility(event) === true) {
let parent = $(this).parent();
if (parent.find('input[name="tabs"]:checked').length > 0) {
parent.find('input[name="tabs"]').prop('checked', false);
} else {
parent.find('input[name="tabs"]').prop('checked', true);
}
}
});
}
});

// focus heading on click
$('input[name=tabs]').click(function () {
$(this).parent('article').find('.acc-heading').focus();
});
// focus heading on click
$('input[name=tabs]').click(function () {
$(this).parent('article').find('.acc-heading').focus();
});

// highlight title on hover
accItem.hover(function () {
accItem.find('.title').removeClass('ht');
$(this).find('.title').addClass('ht');
}, function () {
accItem.find('.title').removeClass('ht');
});
},
};
qgAccordion.init();
}(jQuery));
// highlight title on hover
accItem.hover(function () {
accItem.find('.title').removeClass('ht');
$(this).find('.title').addClass('ht');
}, function () {
accItem.find('.title').removeClass('ht');
});
}
}
Loading