From 3e035c063f067cf6f42a1731251f7c882091f39a Mon Sep 17 00:00:00 2001 From: Joeli Takala Date: Thu, 18 Apr 2024 19:49:55 +0300 Subject: [PATCH 01/14] Search bar updates autocomplete language --- resource/js/vocab-search.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/resource/js/vocab-search.js b/resource/js/vocab-search.js index 1678cef7..2faef965 100644 --- a/resource/js/vocab-search.js +++ b/resource/js/vocab-search.js @@ -45,7 +45,8 @@ const vocabSearch = Vue.createApp({ const mySearchCounter = this.searchCounter + 1 // make sure we can identify this search later in case of several ongoing searches this.searchCounter = mySearchCounter let skosmosSearchUrl = 'rest/v1/' + window.SKOSMOS.vocab + '/search?' - const skosmosSearchUrlParams = new URLSearchParams({ query: this.formatSearchTerm(), lang: window.SKOSMOS.lang, unique: true }) + const skosmosSearchUrlParams = new URLSearchParams({ query: this.formatSearchTerm(), unique: true }) + if (this.selectedLanguage !== 'all') skosmosSearchUrlParams.set('lang', this.selectedLanguage) skosmosSearchUrl += skosmosSearchUrlParams.toString() fetch(skosmosSearchUrl) @@ -148,8 +149,10 @@ const vocabSearch = Vue.createApp({ const searchUrl = vocabHref + 'search?' + searchUrlParams.toString() window.location.href = searchUrl }, - changeLang () { + changeLang (changeEvent) { + this.selectedLanguage = changeEvent.target.value window.SKOSMOS.content_lang = this.selectedLanguage + this.resetSearchTermAndHideDropdown() // TODO: Implement (a normal) page load to change content according to the new content language }, resetSearchTermAndHideDropdown () { @@ -170,7 +173,7 @@ const vocabSearch = Vue.createApp({
From 8036e7e33708e50d472634622a49e0d3d66076e6 Mon Sep 17 00:00:00 2001 From: Joeli Takala Date: Wed, 24 Apr 2024 12:23:20 +0300 Subject: [PATCH 02/14] Choosing the content language and setting the search language cookie --- resource/js/vocab-search.js | 52 ++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/resource/js/vocab-search.js b/resource/js/vocab-search.js index 2faef965..975e17c0 100644 --- a/resource/js/vocab-search.js +++ b/resource/js/vocab-search.js @@ -16,7 +16,7 @@ const vocabSearch = Vue.createApp({ }, mounted () { this.languages = window.SKOSMOS.languageOrder - this.selectedLanguage = window.SKOSMOS.content_lang + this.selectedLanguage = this.parseSearchLang() this.searchCounter = 0 this.languageStrings = window.SKOSMOS.language_strings[window.SKOSMOS.lang] ?? window.SKOSMOS.language_strings.en this.msgs = window.SKOSMOS.msgs[window.SKOSMOS.lang] ?? window.SKOSMOS.msgs.en @@ -68,6 +68,33 @@ const vocabSearch = Vue.createApp({ } return false }, + parseSearchLang () { + //if content language can be found from uri params, use that and update it to SKOSMOS object and to search lang cookie + const urlParams = new URLSearchParams(window.location.search) + const paramLang = urlParams.get('clang') + const anyLang = urlParams.get('anylang') + if (anyLang) { + document.cookie = `SKOSMOS_SEARCH_LANG=${'all'}` + return 'all' + } + if (paramLang) { + this.changeLang(paramLang) + return paramLang + } + //use searchLangCookie if it can be found, otherwise pick content lang from SKOSMOS object + const cookies = document.cookie.split('; ') + const searchLangCookie = cookies.find(cookie => + cookie.startsWith('SKOSMOS_SEARCH_LANG=')) + if (searchLangCookie) { + const selectedLanguage = searchLangCookie.split('=')[1] + if (selectedLanguage !== 'all') { + window.SKOSMOS.content_lang = selectedLanguage + } + return selectedLanguage + } else { + return window.SKOSMOS.content_lang + } + }, renderMatchingPart (searchTerm, label) { if (label) { const searchTermLowerCase = searchTerm.toLowerCase() @@ -145,15 +172,26 @@ const vocabSearch = Vue.createApp({ const currentVocab = window.SKOSMOS.vocab + '/' + window.SKOSMOS.lang + '/' const vocabHref = window.location.href.substring(0, window.location.href.lastIndexOf(window.SKOSMOS.vocab)) + currentVocab const searchUrlParams = new URLSearchParams({ clang: window.SKOSMOS.content_lang, q: this.searchTerm }) - if (this.selectedLanguage === 'all') searchUrlParams.set('anylang', 'on') + if (this.selectedLanguage === 'all') searchUrlParams.set('anylang', 'true') const searchUrl = vocabHref + 'search?' + searchUrlParams.toString() window.location.href = searchUrl }, - changeLang (changeEvent) { - this.selectedLanguage = changeEvent.target.value - window.SKOSMOS.content_lang = this.selectedLanguage + changeLang (lang) { + this.selectedLanguage = lang + document.cookie = `SKOSMOS_SEARCH_LANG=${this.selectedLanguage}` this.resetSearchTermAndHideDropdown() - // TODO: Implement (a normal) page load to change content according to the new content language + }, + changeContentLangAndReload (lang) { + this.changeLang(lang) + const params = new URLSearchParams(window.location.search) + if (lang === 'all') { + params.set('anylang', 'true') + } else { + params.delete('anylang') + params.set('clang', lang) + } + this.$forceUpdate() + window.location.search = params.toString() }, resetSearchTermAndHideDropdown () { this.searchTerm = '' @@ -173,7 +211,7 @@ const vocabSearch = Vue.createApp({
From 2e8f5f26728bd198240b00cf08921c0fe8aecd43 Mon Sep 17 00:00:00 2001 From: Joeli Takala Date: Wed, 24 Apr 2024 12:59:44 +0300 Subject: [PATCH 03/14] Autocomplete search results rendered for multi-language search --- resource/js/vocab-search.js | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/resource/js/vocab-search.js b/resource/js/vocab-search.js index 975e17c0..7df5b6b1 100644 --- a/resource/js/vocab-search.js +++ b/resource/js/vocab-search.js @@ -69,7 +69,7 @@ const vocabSearch = Vue.createApp({ return false }, parseSearchLang () { - //if content language can be found from uri params, use that and update it to SKOSMOS object and to search lang cookie + // if content language can be found from uri params, use that and update it to SKOSMOS object and to search lang cookie const urlParams = new URLSearchParams(window.location.search) const paramLang = urlParams.get('clang') const anyLang = urlParams.get('anylang') @@ -81,7 +81,7 @@ const vocabSearch = Vue.createApp({ this.changeLang(paramLang) return paramLang } - //use searchLangCookie if it can be found, otherwise pick content lang from SKOSMOS object + // use searchLangCookie if it can be found, otherwise pick content lang from SKOSMOS object const cookies = document.cookie.split('; ') const searchLangCookie = cookies.find(cookie => cookie.startsWith('SKOSMOS_SEARCH_LANG=')) @@ -95,8 +95,12 @@ const vocabSearch = Vue.createApp({ return window.SKOSMOS.content_lang } }, - renderMatchingPart (searchTerm, label) { + renderMatchingPart (searchTerm, label, lang = null) { if (label) { + let langSpec = '' + if (lang && this.selectedLanguage === 'all') { + langSpec = ' (' + lang + ')' + } const searchTermLowerCase = searchTerm.toLowerCase() const labelLowerCase = label.toLowerCase() if (labelLowerCase.includes(searchTermLowerCase)) { @@ -105,10 +109,10 @@ const vocabSearch = Vue.createApp({ return { before: label.substring(0, startIndex), match: label.substring(startIndex, endIndex), - after: label.substring(endIndex) + after: label.substring(endIndex) + langSpec } } - return label + return label + langSpec } return null }, @@ -123,21 +127,25 @@ const vocabSearch = Vue.createApp({ renderResults () { // TODO: get the results list form cache if it is implemented const renderedSearchTerm = this.searchTerm // save the search term in case it changes while rendering + this.renderedResultsList.forEach(result => { if ('hiddenLabel' in result) { result.hitType = 'hidden' - result.hit = this.renderMatchingPart(renderedSearchTerm, result.prefLabel) + result.hit = this.renderMatchingPart(renderedSearchTerm, result.prefLabel, result.lang) } else if ('altLabel' in result) { result.hitType = 'alt' - result.hit = this.renderMatchingPart(renderedSearchTerm, result.altLabel) + result.hit = this.renderMatchingPart(renderedSearchTerm, result.altLabel, result.lang) result.hitPref = this.renderMatchingPart(renderedSearchTerm, result.prefLabel) } else { if (this.notationMatches(renderedSearchTerm, result.notation)) { result.hitType = 'notation' - result.hit = this.renderMatchingPart(renderedSearchTerm, result.notation) + result.hit = this.renderMatchingPart(renderedSearchTerm, result.notation, result.lang) + } else if ('matchedPrefLabel' in result) { + result.hitType = 'pref' + result.hit = this.renderMatchingPart(renderedSearchTerm, result.matchedPrefLabel, result.lang) } else if ('prefLabel' in result) { result.hitType = 'pref' - result.hit = this.renderMatchingPart(renderedSearchTerm, result.prefLabel) + result.hit = this.renderMatchingPart(renderedSearchTerm, result.prefLabel, result.lang) } } if ('uri' in result) { // create relative Skosmos page URL from the search result URI From db69cfce503c890046e8acc84e85eccc3ecb76f9 Mon Sep 17 00:00:00 2001 From: Joeli Takala Date: Thu, 18 Apr 2024 19:49:55 +0300 Subject: [PATCH 04/14] Search bar updates autocomplete language --- resource/js/vocab-search.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/resource/js/vocab-search.js b/resource/js/vocab-search.js index 1678cef7..2faef965 100644 --- a/resource/js/vocab-search.js +++ b/resource/js/vocab-search.js @@ -45,7 +45,8 @@ const vocabSearch = Vue.createApp({ const mySearchCounter = this.searchCounter + 1 // make sure we can identify this search later in case of several ongoing searches this.searchCounter = mySearchCounter let skosmosSearchUrl = 'rest/v1/' + window.SKOSMOS.vocab + '/search?' - const skosmosSearchUrlParams = new URLSearchParams({ query: this.formatSearchTerm(), lang: window.SKOSMOS.lang, unique: true }) + const skosmosSearchUrlParams = new URLSearchParams({ query: this.formatSearchTerm(), unique: true }) + if (this.selectedLanguage !== 'all') skosmosSearchUrlParams.set('lang', this.selectedLanguage) skosmosSearchUrl += skosmosSearchUrlParams.toString() fetch(skosmosSearchUrl) @@ -148,8 +149,10 @@ const vocabSearch = Vue.createApp({ const searchUrl = vocabHref + 'search?' + searchUrlParams.toString() window.location.href = searchUrl }, - changeLang () { + changeLang (changeEvent) { + this.selectedLanguage = changeEvent.target.value window.SKOSMOS.content_lang = this.selectedLanguage + this.resetSearchTermAndHideDropdown() // TODO: Implement (a normal) page load to change content according to the new content language }, resetSearchTermAndHideDropdown () { @@ -170,7 +173,7 @@ const vocabSearch = Vue.createApp({
From a7648be24c99b55916cc69300b49199537cd4128 Mon Sep 17 00:00:00 2001 From: Joeli Takala Date: Wed, 24 Apr 2024 12:23:20 +0300 Subject: [PATCH 05/14] Choosing the content language and setting the search language cookie --- resource/js/vocab-search.js | 52 ++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/resource/js/vocab-search.js b/resource/js/vocab-search.js index 2faef965..975e17c0 100644 --- a/resource/js/vocab-search.js +++ b/resource/js/vocab-search.js @@ -16,7 +16,7 @@ const vocabSearch = Vue.createApp({ }, mounted () { this.languages = window.SKOSMOS.languageOrder - this.selectedLanguage = window.SKOSMOS.content_lang + this.selectedLanguage = this.parseSearchLang() this.searchCounter = 0 this.languageStrings = window.SKOSMOS.language_strings[window.SKOSMOS.lang] ?? window.SKOSMOS.language_strings.en this.msgs = window.SKOSMOS.msgs[window.SKOSMOS.lang] ?? window.SKOSMOS.msgs.en @@ -68,6 +68,33 @@ const vocabSearch = Vue.createApp({ } return false }, + parseSearchLang () { + //if content language can be found from uri params, use that and update it to SKOSMOS object and to search lang cookie + const urlParams = new URLSearchParams(window.location.search) + const paramLang = urlParams.get('clang') + const anyLang = urlParams.get('anylang') + if (anyLang) { + document.cookie = `SKOSMOS_SEARCH_LANG=${'all'}` + return 'all' + } + if (paramLang) { + this.changeLang(paramLang) + return paramLang + } + //use searchLangCookie if it can be found, otherwise pick content lang from SKOSMOS object + const cookies = document.cookie.split('; ') + const searchLangCookie = cookies.find(cookie => + cookie.startsWith('SKOSMOS_SEARCH_LANG=')) + if (searchLangCookie) { + const selectedLanguage = searchLangCookie.split('=')[1] + if (selectedLanguage !== 'all') { + window.SKOSMOS.content_lang = selectedLanguage + } + return selectedLanguage + } else { + return window.SKOSMOS.content_lang + } + }, renderMatchingPart (searchTerm, label) { if (label) { const searchTermLowerCase = searchTerm.toLowerCase() @@ -145,15 +172,26 @@ const vocabSearch = Vue.createApp({ const currentVocab = window.SKOSMOS.vocab + '/' + window.SKOSMOS.lang + '/' const vocabHref = window.location.href.substring(0, window.location.href.lastIndexOf(window.SKOSMOS.vocab)) + currentVocab const searchUrlParams = new URLSearchParams({ clang: window.SKOSMOS.content_lang, q: this.searchTerm }) - if (this.selectedLanguage === 'all') searchUrlParams.set('anylang', 'on') + if (this.selectedLanguage === 'all') searchUrlParams.set('anylang', 'true') const searchUrl = vocabHref + 'search?' + searchUrlParams.toString() window.location.href = searchUrl }, - changeLang (changeEvent) { - this.selectedLanguage = changeEvent.target.value - window.SKOSMOS.content_lang = this.selectedLanguage + changeLang (lang) { + this.selectedLanguage = lang + document.cookie = `SKOSMOS_SEARCH_LANG=${this.selectedLanguage}` this.resetSearchTermAndHideDropdown() - // TODO: Implement (a normal) page load to change content according to the new content language + }, + changeContentLangAndReload (lang) { + this.changeLang(lang) + const params = new URLSearchParams(window.location.search) + if (lang === 'all') { + params.set('anylang', 'true') + } else { + params.delete('anylang') + params.set('clang', lang) + } + this.$forceUpdate() + window.location.search = params.toString() }, resetSearchTermAndHideDropdown () { this.searchTerm = '' @@ -173,7 +211,7 @@ const vocabSearch = Vue.createApp({
From 143bb22ae385e107c63d76949197aeb85749d305 Mon Sep 17 00:00:00 2001 From: Joeli Takala Date: Wed, 24 Apr 2024 12:59:44 +0300 Subject: [PATCH 06/14] Autocomplete search results rendered for multi-language search --- resource/js/vocab-search.js | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/resource/js/vocab-search.js b/resource/js/vocab-search.js index 975e17c0..7df5b6b1 100644 --- a/resource/js/vocab-search.js +++ b/resource/js/vocab-search.js @@ -69,7 +69,7 @@ const vocabSearch = Vue.createApp({ return false }, parseSearchLang () { - //if content language can be found from uri params, use that and update it to SKOSMOS object and to search lang cookie + // if content language can be found from uri params, use that and update it to SKOSMOS object and to search lang cookie const urlParams = new URLSearchParams(window.location.search) const paramLang = urlParams.get('clang') const anyLang = urlParams.get('anylang') @@ -81,7 +81,7 @@ const vocabSearch = Vue.createApp({ this.changeLang(paramLang) return paramLang } - //use searchLangCookie if it can be found, otherwise pick content lang from SKOSMOS object + // use searchLangCookie if it can be found, otherwise pick content lang from SKOSMOS object const cookies = document.cookie.split('; ') const searchLangCookie = cookies.find(cookie => cookie.startsWith('SKOSMOS_SEARCH_LANG=')) @@ -95,8 +95,12 @@ const vocabSearch = Vue.createApp({ return window.SKOSMOS.content_lang } }, - renderMatchingPart (searchTerm, label) { + renderMatchingPart (searchTerm, label, lang = null) { if (label) { + let langSpec = '' + if (lang && this.selectedLanguage === 'all') { + langSpec = ' (' + lang + ')' + } const searchTermLowerCase = searchTerm.toLowerCase() const labelLowerCase = label.toLowerCase() if (labelLowerCase.includes(searchTermLowerCase)) { @@ -105,10 +109,10 @@ const vocabSearch = Vue.createApp({ return { before: label.substring(0, startIndex), match: label.substring(startIndex, endIndex), - after: label.substring(endIndex) + after: label.substring(endIndex) + langSpec } } - return label + return label + langSpec } return null }, @@ -123,21 +127,25 @@ const vocabSearch = Vue.createApp({ renderResults () { // TODO: get the results list form cache if it is implemented const renderedSearchTerm = this.searchTerm // save the search term in case it changes while rendering + this.renderedResultsList.forEach(result => { if ('hiddenLabel' in result) { result.hitType = 'hidden' - result.hit = this.renderMatchingPart(renderedSearchTerm, result.prefLabel) + result.hit = this.renderMatchingPart(renderedSearchTerm, result.prefLabel, result.lang) } else if ('altLabel' in result) { result.hitType = 'alt' - result.hit = this.renderMatchingPart(renderedSearchTerm, result.altLabel) + result.hit = this.renderMatchingPart(renderedSearchTerm, result.altLabel, result.lang) result.hitPref = this.renderMatchingPart(renderedSearchTerm, result.prefLabel) } else { if (this.notationMatches(renderedSearchTerm, result.notation)) { result.hitType = 'notation' - result.hit = this.renderMatchingPart(renderedSearchTerm, result.notation) + result.hit = this.renderMatchingPart(renderedSearchTerm, result.notation, result.lang) + } else if ('matchedPrefLabel' in result) { + result.hitType = 'pref' + result.hit = this.renderMatchingPart(renderedSearchTerm, result.matchedPrefLabel, result.lang) } else if ('prefLabel' in result) { result.hitType = 'pref' - result.hit = this.renderMatchingPart(renderedSearchTerm, result.prefLabel) + result.hit = this.renderMatchingPart(renderedSearchTerm, result.prefLabel, result.lang) } } if ('uri' in result) { // create relative Skosmos page URL from the search result URI From 4b99dd17de1e3db81c1ba15d78f9b7606e7548a6 Mon Sep 17 00:00:00 2001 From: Joeli Takala Date: Wed, 24 Apr 2024 15:35:14 +0300 Subject: [PATCH 07/14] Fixed a search parameter --- tests/cypress/template/vocab-search-bar.cy.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cypress/template/vocab-search-bar.cy.js b/tests/cypress/template/vocab-search-bar.cy.js index b5f1ce81..113a06fb 100644 --- a/tests/cypress/template/vocab-search-bar.cy.js +++ b/tests/cypress/template/vocab-search-bar.cy.js @@ -31,7 +31,7 @@ describe('Vocab search bar', () => { cy.get('#search-button').click(); //Verify the search page url (search result page tests are elsewhere) - cy.url().should('include', 'q=Katt').and('include', 'anylang=on'); + cy.url().should('include', 'q=Katt').and('include', 'anylang=true'); }) it('Writing in the text field triggers the autocomplete results list', () => { From 23bdcfe4c7cd5f83f3c2a0dcac1c9921c76f3d3f Mon Sep 17 00:00:00 2001 From: Joeli Takala Date: Wed, 24 Apr 2024 16:06:34 +0300 Subject: [PATCH 08/14] Added cookie tests. Refactored vocab search bar tests and divided into subsections. --- tests/cypress/template/vocab-search-bar.cy.js | 250 ++++++++++-------- 1 file changed, 138 insertions(+), 112 deletions(-) diff --git a/tests/cypress/template/vocab-search-bar.cy.js b/tests/cypress/template/vocab-search-bar.cy.js index 113a06fb..a9b5640a 100644 --- a/tests/cypress/template/vocab-search-bar.cy.js +++ b/tests/cypress/template/vocab-search-bar.cy.js @@ -1,157 +1,183 @@ describe('Vocab search bar', () => { - it('search can be done with a chosen content language', () => { - // go to YSO vocab front page - cy.visit('/yso/fi/') - // Select an option from the dropdown - cy.get('#search-wrapper select').select('sv'); + describe('Search Language', () => { + it('search can be done with a chosen content language', () => { + // go to YSO vocab front page + cy.visit('/yso/fi/') - // Enter a search term - cy.get('#search-wrapper input').type('Katt'); + // Select an option from the dropdown + cy.get('#search-wrapper select').select('sv'); - // Click the search button - cy.get('#search-button').click(); + // Enter a search term + cy.get('#search-wrapper input').type('Katt'); - //Verify the search page url (search result page tests are elsewhere) - cy.url().should('include', 'q=Katt').and('include', 'clang=sv'); + // Click the search button + cy.get('#search-button').click(); - }) + // Verify the search page url (search result page tests are elsewhere) + cy.url().should('include', 'q=Katt').and('include', 'clang=sv'); + }) + + it('search can be done with all languages', () => { + // go to YSO vocab front page + cy.visit('/yso/fi/') - it('search can be done with all languages', () => { - // go to YSO vocab front page - cy.visit('/yso/fi/') + // Choose 'all' languages + cy.get('#search-wrapper select').select('all'); - // Choose 'all' languages - cy.get('#search-wrapper select').select('all'); + // Enter a search term + cy.get('#search-wrapper input').type('Katt'); - // Enter a search term - cy.get('#search-wrapper input').type('Katt'); + // Click the search button + cy.get('#search-button').click(); - // Click the search button - cy.get('#search-button').click(); + // Verify the search page url (search result page tests are elsewhere) + cy.url().should('include', 'q=Katt').and('include', 'anylang=true'); + }) + }); - //Verify the search page url (search result page tests are elsewhere) - cy.url().should('include', 'q=Katt').and('include', 'anylang=true'); - }) + describe('Autocomplete', () => { + it('Writing in the text field triggers the autocomplete results list', () => { + // go to YSO vocab front page + cy.visit('/yso/fi/') - it('Writing in the text field triggers the autocomplete results list', () => { - // go to YSO vocab front page - cy.visit('/yso/fi/') + cy.get('#search-field').type('kas'); // perform autocomplete search + cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible').children().should('have.length.greaterThan', 2); + }) - cy.get('#search-field').type('kas'); // perform autocomplete search - cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible').children().should('have.length.greaterThan', 2); - }) + it('Special characters can be used in the search', () => { + // go to YSO vocab front page + cy.visit('/yso/fi/') - it('No results message is displayed if no results are found', () => { - // go to YSO vocab front page - cy.visit('/yso/en/') + cy.get('#search-field').type('*tus (*'); + cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible'); // the autocomplete should appear - cy.get('#search-field').type('kissa'); // even if the search yields no results, there shoulde a single line in the result list - cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible').children().should('have.length.greaterThan', 0); - cy.get('#search-autocomplete-results').within(() => { - cy.get('li').eq(0).invoke('text').should('contain', 'No results') // the single result should display a no results message + cy.get('#search-autocomplete-results').within(() => { // the first result should have text ajoitus (historia) + cy.get('li').first().should('contain', 'ajoitus (historia)') }) - }) + }) - it('No results are displayed for autocomplete if there is not at leas two charecters in the search term', () => { - // go to YSO vocab front page - cy.visit('/yso/en/') + it('No results message is displayed if no results are found', () => { + // go to YSO vocab front page + cy.visit('/yso/en/') - cy.get('#search-field').type('k'); // even if the search yields no results, there shoulde a single line in the result list - cy.get('#search-autocomplete-results', { timeout: 20000 }).should('not.be.visible'); - }) + cy.get('#search-field').type('kissa'); // even if the search yields no results, there shoulde a single line in the result list + cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible').children().should('have.length.greaterThan', 0); + cy.get('#search-autocomplete-results').within(() => { + cy.get('li').eq(0).invoke('text').should('contain', 'No results') // the single result should display a no results message + }) + }) - it('The autocomplete list should not change due to previous searches completing', () => { - // go to YSO vocab front page - cy.visit('/yso/fi/') + it('No results are displayed for autocomplete if there is not at leas two charecters in the search term', () => { + // go to YSO vocab front page + cy.visit('/yso/en/') - cy.get('#search-field').type('ka'); - cy.wait(300); - cy.get('#search-field').type('i'); - cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible'); // the autocomplete should appear - cy.get('#search-autocomplete-results').children().should('have.length', 1) - cy.wait(10000); // wait extra 10 seconds to see if the 'ka' search adds results to the list - cy.get('#search-autocomplete-results').children().should('have.length', 1) - }) + cy.get('#search-field').type('k'); // even if the search yields no results, there shoulde a single line in the result list + cy.get('#search-autocomplete-results', { timeout: 20000 }).should('not.be.visible'); + }) - it('Clear button should hide the autocomplete list', () => { - // go to YSO vocab front page - cy.visit('/yso/en/') + it('The autocomplete list should not change due to previous searches completing', () => { + // go to YSO vocab front page + cy.visit('/yso/fi/') + + cy.get('#search-field').type('ka'); + cy.wait(300); + cy.get('#search-field').type('i'); + cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible'); // the autocomplete should appear + cy.get('#search-autocomplete-results').children().should('have.length', 1) + cy.wait(5000); // wait extra 5 seconds to see if the 'ka' search adds results to the list + cy.get('#search-autocomplete-results').children().should('have.length', 1) + }) - cy.get('#search-field').type('kas'); - cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible'); // the autocomplete should appear + it('Clear button should hide the autocomplete list', () => { + // go to YSO vocab front page + cy.visit('/yso/en/') - cy.get('#clear-button').click() - cy.get('#search-autocomplete-results').should('not.be.visible'); // the autocomplete should disappear - }) + cy.get('#search-field').type('kas'); + cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible'); // the autocomplete should appear - it('Emptying the text search field hides the autocomplete list', () => { - // go to YSO vocab front page - cy.visit('/yso/en/') + cy.get('#clear-button').click() + cy.get('#search-autocomplete-results').should('not.be.visible'); // the autocomplete should disappear + }) - cy.get('#search-field').type('kis'); - cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible'); // the autocomplete should appear + it('Emptying the text search field hides the autocomplete list', () => { + // go to YSO vocab front page + cy.visit('/yso/en/') - cy.get('#search-field').clear(); - cy.get('#search-autocomplete-results').should('not.be.visible'); // the autocomplete should disappear - }) + cy.get('#search-field').type('kis'); + cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible'); // the autocomplete should appear - it('Clicking outside of the autocomplete list hides the autocomplete list', () => { - // go to YSO vocab front page - cy.visit('/yso/en/') + cy.get('#search-field').clear(); + cy.get('#search-autocomplete-results').should('not.be.visible'); // the autocomplete should disappear + }) - cy.get('#search-field').type('kas'); - cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible'); // the autocomplete should appear + it('Clicking outside of the autocomplete list hides the autocomplete list', () => { + // go to YSO vocab front page + cy.visit('/yso/en/') - cy.get('#main-container').click({ force: true }); // using force true to click on elements not considered actionable - cy.get('#search-autocomplete-results').should('not.be.visible'); // the autocomplete should disappear - }) + cy.get('#search-field').type('kas'); + cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible'); // the autocomplete should appear - it('AltLabel search results should bold the matching parts of altLabel', () => { - // go to YSO vocab front page - cy.visit('/yso/fi/') + cy.get('#main-container').click({ force: true }); // using force true to click on elements not considered actionable + cy.get('#search-autocomplete-results').should('not.be.visible'); // the autocomplete should disappear + }) + }); - cy.get('#search-field').type('assyro'); - cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible'); // the autocomplete should appear + describe('Search Result Rendering', () => { + it('AltLabel search results should bold the matching parts of altLabel', () => { + // go to YSO vocab front page + cy.visit('/yso/fi/') - cy.get('#search-autocomplete-results').within(() => { // the first result should have matching part of text 'assyrologia' appearing in bold - cy.get('li').last().find('b').eq(0).should('have.text', 'assyro') + cy.get('#search-field').type('assyro'); + cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible'); // the autocomplete should appear + + cy.get('#search-autocomplete-results').within(() => { // the first result should have matching part of text 'assyrologia' appearing in bold + cy.get('li').last().find('b').eq(0).should('have.text', 'assyro') + }) }) - }) - it('AltLabel search results should be displayed in italics', () => { - // go to YSO vocab front page - cy.visit('/yso/fi/') + it('AltLabel search results should be displayed in italics', () => { + // go to YSO vocab front page + cy.visit('/yso/fi/') - cy.get('#search-field').type('assyro'); - cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible'); // the autocomplete should appear + cy.get('#search-field').type('assyro'); + cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible'); // the autocomplete should appear - cy.get('#search-autocomplete-results').within(() => { // the first result should have text 'assyrologia' appearing in italics - cy.get('li').last().find('i').eq(0).should('contain.text', 'assyrologia') + cy.get('#search-autocomplete-results').within(() => { // the first result should have text 'assyrologia' appearing in italics + cy.get('li').last().find('i').eq(0).should('contain.text', 'assyrologia') + }) }) - }) - it('Notation search results should bold the matching parts of the notation', () => { - // go to YSO vocab front page - cy.visit('/yso/fi/') + it('Notation search results should bold the matching parts of the notation', () => { + // go to YSO vocab front page + cy.visit('/yso/fi/') - cy.get('#search-field').type('51'); - cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible'); // the autocomplete should appear + cy.get('#search-field').type('51'); + cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible'); // the autocomplete should appear - cy.get('#search-autocomplete-results').within(() => { // the first result should have text '51' appearing in bold - cy.get('li').last().find('b').eq(0).should('have.text', '51') + cy.get('#search-autocomplete-results').within(() => { // the first result should have text '51' appearing in bold + cy.get('li').last().find('b').eq(0).should('have.text', '51') + }) }) - }) + }); - it('Special characters can be used in the search', () => { - // go to YSO vocab front page - cy.visit('/yso/fi/') + describe('Cookie Management', () => { + it('The search language cookie is set', () => { + cy.visit('/yso/fi/'); - cy.get('#search-field').type('*tus (*'); - cy.get('#search-autocomplete-results', { timeout: 20000 }).should('be.visible'); // the autocomplete should appear + // Select an option from the dropdown to set the search language + cy.get('#search-wrapper select').select('sv'); - cy.get('#search-autocomplete-results').within(() => { // the first result should have text ajoitus (historia) - cy.get('li').first().should('contain', 'ajoitus (historia)') - }) - }) + // Test that the cookie has been set correctly + cy.getCookie('SKOSMOS_SEARCH_LANG').should('have.property', 'value', 'sv'); + }); + + it('The search language cookie is read', () => { + cy.setCookie('SKOSMOS_SEARCH_LANG', 'en'); + cy.visit('/yso/fi/'); + + // Test that the cookie value has been read and used to initialize the language selector + cy.get('#search-wrapper select').should('have.value', 'en'); + }); + }); }) From c3978c566fbc39a02ea45d208c358c1a50ddfc0b Mon Sep 17 00:00:00 2001 From: Joeli Takala Date: Wed, 24 Apr 2024 16:15:56 +0300 Subject: [PATCH 09/14] Changed the search language cookie to global context --- resource/js/vocab-search.js | 4 ++-- tests/cypress/template/vocab-search-bar.cy.js | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/resource/js/vocab-search.js b/resource/js/vocab-search.js index 7df5b6b1..b51e1a27 100644 --- a/resource/js/vocab-search.js +++ b/resource/js/vocab-search.js @@ -74,7 +74,7 @@ const vocabSearch = Vue.createApp({ const paramLang = urlParams.get('clang') const anyLang = urlParams.get('anylang') if (anyLang) { - document.cookie = `SKOSMOS_SEARCH_LANG=${'all'}` + document.cookie = `SKOSMOS_SEARCH_LANG=${'all'};path=/` return 'all' } if (paramLang) { @@ -186,7 +186,7 @@ const vocabSearch = Vue.createApp({ }, changeLang (lang) { this.selectedLanguage = lang - document.cookie = `SKOSMOS_SEARCH_LANG=${this.selectedLanguage}` + document.cookie = `SKOSMOS_SEARCH_LANG=${this.selectedLanguage};path=/` this.resetSearchTermAndHideDropdown() }, changeContentLangAndReload (lang) { diff --git a/tests/cypress/template/vocab-search-bar.cy.js b/tests/cypress/template/vocab-search-bar.cy.js index a9b5640a..9894535b 100644 --- a/tests/cypress/template/vocab-search-bar.cy.js +++ b/tests/cypress/template/vocab-search-bar.cy.js @@ -173,6 +173,7 @@ describe('Vocab search bar', () => { }); it('The search language cookie is read', () => { + cy.visit('/'); // setting the cookie at the front page to make sure the cookies are set globally cy.setCookie('SKOSMOS_SEARCH_LANG', 'en'); cy.visit('/yso/fi/'); From a6328628c21e2b883657d0341118bb9a916ffe8e Mon Sep 17 00:00:00 2001 From: Joeli Takala Date: Thu, 25 Apr 2024 10:49:48 +0300 Subject: [PATCH 10/14] Setting a relative path for the search language cookie --- resource/js/vocab-search.js | 8 +++++++- src/view/scripts.inc | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/resource/js/vocab-search.js b/resource/js/vocab-search.js index b51e1a27..3970592a 100644 --- a/resource/js/vocab-search.js +++ b/resource/js/vocab-search.js @@ -186,7 +186,13 @@ const vocabSearch = Vue.createApp({ }, changeLang (lang) { this.selectedLanguage = lang - document.cookie = `SKOSMOS_SEARCH_LANG=${this.selectedLanguage};path=/` + // Setting the cookie path to be the relative part of the baseHref if it is provided + const cookiePath = "/" + if (window.SKOSMOS.baseHref && window.SKOSMOS.baseHref.replace(window.origin, '')) { + cookiePath = window.SKOSMOS.baseHref.replace(window.origin, '') + } + document.cookie = `SKOSMOS_SEARCH_LANG=${this.selectedLanguage};path=${cookiePath}` + this.resetSearchTermAndHideDropdown() }, changeContentLangAndReload (lang) { diff --git a/src/view/scripts.inc b/src/view/scripts.inc index 87a4d99d..be8641c9 100644 --- a/src/view/scripts.inc +++ b/src/view/scripts.inc @@ -24,6 +24,7 @@ window.SKOSMOS = { {%- if request.plugins.callbacks ~%} "pluginCallbacks": [{% for function in request.plugins.callbacks %}{% if not loop.first %}, {% endif %}"{{ function }}"{% endfor %}], {%- endif ~%} + "baseHref": "{{ BaseHref }}", "language_strings": { "fi": { "fi": "suomi", "en": "englanti", "se": "pohjoissaame", From ef539f7bc9b9176c7b4962d1920c0cb0f4c129ef Mon Sep 17 00:00:00 2001 From: Joeli Takala Date: Thu, 25 Apr 2024 11:02:17 +0300 Subject: [PATCH 11/14] JS fix --- resource/js/vocab-search.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resource/js/vocab-search.js b/resource/js/vocab-search.js index 3970592a..f5c05275 100644 --- a/resource/js/vocab-search.js +++ b/resource/js/vocab-search.js @@ -187,7 +187,7 @@ const vocabSearch = Vue.createApp({ changeLang (lang) { this.selectedLanguage = lang // Setting the cookie path to be the relative part of the baseHref if it is provided - const cookiePath = "/" + let cookiePath = '/' if (window.SKOSMOS.baseHref && window.SKOSMOS.baseHref.replace(window.origin, '')) { cookiePath = window.SKOSMOS.baseHref.replace(window.origin, '') } From 6d1bd328b81f61f0efd4eb71a0d052c0a250f2f7 Mon Sep 17 00:00:00 2001 From: Joeli Takala Date: Thu, 25 Apr 2024 11:18:33 +0300 Subject: [PATCH 12/14] Refactored to use separate function for setting the search language cookie --- resource/js/vocab-search.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/resource/js/vocab-search.js b/resource/js/vocab-search.js index f5c05275..ff29a935 100644 --- a/resource/js/vocab-search.js +++ b/resource/js/vocab-search.js @@ -74,7 +74,7 @@ const vocabSearch = Vue.createApp({ const paramLang = urlParams.get('clang') const anyLang = urlParams.get('anylang') if (anyLang) { - document.cookie = `SKOSMOS_SEARCH_LANG=${'all'};path=/` + this.setSearchLangCookie('all') return 'all' } if (paramLang) { @@ -186,13 +186,7 @@ const vocabSearch = Vue.createApp({ }, changeLang (lang) { this.selectedLanguage = lang - // Setting the cookie path to be the relative part of the baseHref if it is provided - let cookiePath = '/' - if (window.SKOSMOS.baseHref && window.SKOSMOS.baseHref.replace(window.origin, '')) { - cookiePath = window.SKOSMOS.baseHref.replace(window.origin, '') - } - document.cookie = `SKOSMOS_SEARCH_LANG=${this.selectedLanguage};path=${cookiePath}` - + this.setSearchLangCookie(lang) this.resetSearchTermAndHideDropdown() }, changeContentLangAndReload (lang) { @@ -218,6 +212,14 @@ const vocabSearch = Vue.createApp({ showAutoComplete () { this.showDropdown = true this.$forceUpdate() + }, + setSearchLangCookie (lang) { + // The cookie path should be relative if the baseHref is known + let cookiePath = '/' + if (window.SKOSMOS.baseHref && window.SKOSMOS.baseHref.replace(window.origin, '')) { + cookiePath = window.SKOSMOS.baseHref.replace(window.origin, '') + } + document.cookie = `SKOSMOS_SEARCH_LANG=${this.selectedLanguage};path=${cookiePath}` } }, template: ` From 8b8daaa2bb0cb9088d2919b99796b73bcca1b42c Mon Sep 17 00:00:00 2001 From: Joeli Takala Date: Thu, 25 Apr 2024 13:22:10 +0300 Subject: [PATCH 13/14] Fixed a brainfart in setting the search language & cookie --- resource/js/vocab-search.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resource/js/vocab-search.js b/resource/js/vocab-search.js index ff29a935..9c46f21c 100644 --- a/resource/js/vocab-search.js +++ b/resource/js/vocab-search.js @@ -74,7 +74,7 @@ const vocabSearch = Vue.createApp({ const paramLang = urlParams.get('clang') const anyLang = urlParams.get('anylang') if (anyLang) { - this.setSearchLangCookie('all') + this.changeLang('all') return 'all' } if (paramLang) { From d9dc023cb3d484c4cf8e273205d89ffcbf8d58e0 Mon Sep 17 00:00:00 2001 From: Joeli Takala Date: Thu, 25 Apr 2024 13:30:38 +0300 Subject: [PATCH 14/14] Added a test for the separation of content language and search language --- tests/cypress/template/vocab-search-bar.cy.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/cypress/template/vocab-search-bar.cy.js b/tests/cypress/template/vocab-search-bar.cy.js index 9894535b..9753465f 100644 --- a/tests/cypress/template/vocab-search-bar.cy.js +++ b/tests/cypress/template/vocab-search-bar.cy.js @@ -34,6 +34,21 @@ describe('Vocab search bar', () => { // Verify the search page url (search result page tests are elsewhere) cy.url().should('include', 'q=Katt').and('include', 'anylang=true'); }) + + it('search with all languages retains the previously chosen content language', () => { + // go to YSO vocab front page + cy.visit('/yso/fi/') + + // Choose 'sv' for search & content language + cy.get('#search-wrapper select').select('sv'); + + // Choose 'all' for search language + cy.get('#search-wrapper select').select('all'); + + // Verify the search page url has the previously chosen language as the content language + cy.url().should('include', 'clang=sv'); + }) + }); describe('Autocomplete', () => {