Skip to content

Commit

Permalink
T270468: Add tips feature (#313)
Browse files Browse the repository at this point in the history
* Add tips feature

* Update gifs

* Update tip height

* Add goto methods

* Create tip popups with content object

* Fix indentation

* Bring goToRandomArticle back to Search

* Disable try option when offline

* Update text and size

* Introduce skip intro option

* Update margins

* Add tips tests

* Clear article history when trying out tips

* Update tip text style

* Update tips styling

* Display scrollbar for tips text
  • Loading branch information
medied authored Feb 24, 2021
1 parent 7f62acd commit 0321203
Show file tree
Hide file tree
Showing 20 changed files with 397 additions and 15 deletions.
87 changes: 87 additions & 0 deletions cypress/integration/tips-spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/// <reference types="Cypress" />

import * as enJson from '../../i18n/en.json'
import { TipsPage } from '../page-objects/tips-page'
import { PopupPage } from '../page-objects/popup-page'
import { SearchPage } from '../page-objects/search-page'

const searchPage = new SearchPage()
const tipsPage = new TipsPage()
const popupPage = new PopupPage()
const tipsMenuListEnglishText = [enJson['tips-read'],
enJson['tips-search'],
enJson['tips-switch'],
enJson['tips-about']]

describe('Tips page', () => {
var firstElementOfTheTipsMenuList
beforeEach(() => {
cy.navigateToHomePage()
searchPage.navigateToTipsPage()
firstElementOfTheTipsMenuList = tipsPage.tipsList().children().first()
})

it('show all the items in the list', () => {
tipsPage.tipsList().should('have.text', tipsMenuListEnglishText.join(''))
})

it('down arrow changes selection', () => {
firstElementOfTheTipsMenuList.should('have.attr', 'nav-selected', 'true')
firstElementOfTheTipsMenuList.next().should('have.attr', 'nav-selected', 'false')
cy.downArrow()
tipsPage.tipsList().children().first().should('have.attr', 'nav-selected', 'false')
firstElementOfTheTipsMenuList.next().should('have.attr', 'nav-selected', 'true')
})

it('only the first element should be selected on load', () => {
cy.get('.list').children().first().should('have.attr', 'nav-selected', 'true')
firstElementOfTheTipsMenuList.next().should('have.attr', 'nav-selected', 'false')
})

it('navigates through all tips', () => {
cy.enter()
popupPage.getFullscreenContent().get('.tip-header').should('have.text', enJson['tip-read-header'])
cy.getRightSoftkeyButton().click()
popupPage.getFullscreenContent().get('.tip-header').should('have.text', enJson['tip-search-header'])
cy.getRightSoftkeyButton().click()
popupPage.getFullscreenContent().get('.tip-header').should('have.text', enJson['tip-switch-header'])
cy.getRightSoftkeyButton().click()
popupPage.getFullscreenContent().get('.tip-header').should('have.text', enJson['tip-about-header'])
cy.getLeftSoftkeyButton().click()
tipsPage.tipsList().children().first().should('have.attr', 'nav-selected', 'true')
})

it('check read tip', () => {
cy.enter()
popupPage.getFullscreenContent().get('.tip-header').should('have.text', enJson['tip-read-header'])
popupPage.getFullscreenContent().get('.tip-text').should('have.text', enJson['tip-read-message'])
popupPage.getFullscreenContent().get('.tip-animation').should('have.attr', 'style').and('contains', 'tip-read-animation.gif')
cy.getCenterSoftkeyButton().click()
cy.getRightSoftkeyButton().should('have.text', enJson['softkey-menu'])
})

it('check search tip', () => {
cy.downArrow().enter()
popupPage.getFullscreenContent().get('.tip-header').should('have.text', enJson['tip-search-header'])
popupPage.getFullscreenContent().get('.tip-text').should('have.text', enJson['tip-search-message'])
popupPage.getFullscreenContent().get('.tip-animation').should('have.attr', 'style').and('contains', 'tip-search-animation.gif')
cy.getCenterSoftkeyButton().click()
cy.getRightSoftkeyButton().should('have.text', enJson['softkey-settings'])
})

it('check switch tip', () => {
cy.downArrow(2).enter()
popupPage.getFullscreenContent().get('.tip-header').should('have.text', enJson['tip-switch-header'])
popupPage.getFullscreenContent().get('.tip-text').should('have.text', enJson['tip-switch-message'])
popupPage.getFullscreenContent().get('.tip-animation').should('have.attr', 'style').and('contains', 'tip-switch-animation.gif')
cy.getCenterSoftkeyButton().click()
cy.getRightSoftkeyButton().should('have.text', enJson['softkey-menu'])
})

it('check about tip', () => {
cy.downArrow(3).enter()
popupPage.getFullscreenContent().get('.tip-header').should('have.text', enJson['tip-about-header'])
popupPage.getFullscreenContent().get('.tip-text').should('have.text', enJson['tip-about-message'])
popupPage.getFullscreenContent().get('.tip-image').should('have.attr', 'style').and('contains', 'onboarding-0.png')
})
})
4 changes: 4 additions & 0 deletions cypress/page-objects/popup-page.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ export class PopupPage {
return cy.get('.popup .popup-content .content')
}

getFullscreenContent () {
return cy.get('.popup .popup-content.fullscreen')
}

getText () {
return cy.get('.preview-text')
}
Expand Down
4 changes: 4 additions & 0 deletions cypress/page-objects/search-page.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ export class SearchPage {
cy.clickSettingsButton()
}

navigateToTipsPage () {
cy.clickTipsButton()
}

getSearchTextBox () {
return cy.get('input[type=text]')
}
Expand Down
5 changes: 5 additions & 0 deletions cypress/page-objects/tips-page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export class TipsPage {
tipsList () {
return cy.get('.list')
}
}
4 changes: 4 additions & 0 deletions cypress/support/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ Cypress.Commands.add('clickSettingsButton', () => {
cy.getRightSoftkeyButton().contains(enJson['softkey-settings']).click()
})

Cypress.Commands.add('clickTipsButton', () => {
cy.getLeftSoftkeyButton().contains(enJson['softkey-tips']).click()
})

Cypress.Commands.add('clickMenuButton', () => {
cy.getRightSoftkeyButton().contains(enJson['softkey-menu']).click()
})
Expand Down
15 changes: 15 additions & 0 deletions i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@
"softkey-skip": "Skip",
"softkey-get-started": "Get started",
"softkey-refresh": "Refresh",
"softkey-tips": "Tips",
"softkey-try": "Try",
"suggested-articles": "Suggested articles",
"reference-title": "Reference [$1]",
"offline-message": "No internet connection",
Expand All @@ -77,6 +79,19 @@
"textsize-preview": "Article text will look like this.",
"textsize-label-small": "Small",
"textsize-label-large": "Large",
"tips-header": "Tips",
"tips-read": "How to read an article?",
"tips-search": "How to search for an article?",
"tips-switch": "How to switch between links?",
"tips-about": "What is Wikipedia?",
"tip-read-header": "Read article",
"tip-read-message": "Use quick links or options key to read articles in several languages, view gallery, and more.",
"tip-search-header": "Search article",
"tip-search-message": "Type in search box to read articles about people, places, and things from all around the world.",
"tip-switch-header": "Switch links",
"tip-switch-message": "Use left or right keys to select links present in an article to expand your knowledge.",
"tip-about-header": "About Wikipedia",
"tip-about-message": "Wikipedia is a free knowledge resource collaboratively written by volunteers around the world.",
"toc-footer": "Suggested articles",
"view-in-browser": "View article in browser",
"about-app-message": "Made by the Wikimedia Foundation with the help of volunteers like you.",
Expand Down
15 changes: 15 additions & 0 deletions i18n/qqq.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@
"softkey-skip": "Label of the skip softkey",
"softkey-get-started": "Label of the get started softkey",
"softkey-refresh": "Label of the refresh softkey. Shown on the article error page.",
"softkey-tips": "Label of the tips softkey",
"softkey-try": "Label of the try softkey",
"suggested-articles": "Label of the Suggested articles section. Shown in the footer",
"reference-title": "Header of the reference preview popup.\n* $1 - Number of the current reference.",
"offline-message": "Message to be display at the top of the screen when there is no internet connection.",
Expand All @@ -78,6 +80,19 @@
"textsize-preview": "Label of the preview text to set the text size. Shown in the Text Size page.",
"textsize-label-small": "Label of the small text indicator. Shown in the Text Size page.",
"textsize-label-large": "Label of the large text indicator. Shown in the Text Size page.",
"tips-header": "Header for the Tips component",
"tips-read": "Label of the reading tip",
"tips-search": "Label of the searching tip",
"tips-switch": "Label of the links switching tip",
"tips-about": "Label of the about wikipedia tip",
"tip-read-header": "Header for the how to read tip",
"tip-read-message": "Message for the how to read tip",
"tip-search-header": "Header for the how to search tip",
"tip-search-message": "Message for the how to search tip",
"tip-switch-header": "Header for the how to switch links tip",
"tip-switch-message": "Message for the how to switch links tip",
"tip-about-header": "Header for the about Wikipedia tip",
"tip-about-message": "Message for the about Wikipedia tip",
"toc-footer": "Label in the sections for the footer link",
"view-in-browser": "Label for the view in browser link. Shown in the footer",
"about-app-message": "Main message in About App page",
Expand Down
Binary file added images/tip-read-animation.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/tip-search-animation.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/tip-switch-animation.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion src/components/Routes.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { h } from 'preact'
import { Router, route } from 'preact-router'
import { createHashHistory } from 'history'
import { Article, Search, Settings, Language, Onboarding } from 'components'
import { Article, Search, Settings, Tips, Language, Onboarding } from 'components'
import { onboarding } from 'utils'

export const Routes = ({ onRouteChange }) => {
Expand All @@ -16,6 +16,7 @@ export const Routes = ({ onRouteChange }) => {
<Onboarding path='/onboarding' />
<Search path='/' />
<Settings path='/settings' />
<Tips path='/tips' />
<Article path='/article/:lang/:title/:anchor?' />
<Language path='/language' />
</Router>
Expand Down
30 changes: 19 additions & 11 deletions src/components/Search.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import {
} from 'hooks'
import {
articleHistory, goto, getAppLanguage,
isRandomEnabled, confirmDialog, isConsentGranted
isRandomEnabled, confirmDialog, skipIntroAnchor,
isConsentGranted
} from 'utils'
import { getRandomArticleTitle } from 'api'

Expand All @@ -31,6 +32,8 @@ export const Search = () => {
const { index, key } = getCurrent()
if (index) {
goto.article(lang, key)
} else if (isRandomEnabled() && !query) {
goToRandomArticle()
}
}
}
Expand Down Expand Up @@ -60,24 +63,17 @@ export const Search = () => {
})
}

const goToRandomArticle = () => {
const [promise] = getRandomArticleTitle(lang)

promise.then(title => {
goto.article(lang, title)
})
}

const allowUsage = () => {
return isOnline || consentGranted
}

useSoftkey('Search', {
right: allowUsage() ? i18n('softkey-settings') : '',
onKeyRight: allowUsage() ? () => { window.location.hash = '/settings' } : null,
onKeyRight: allowUsage() ? goto.settings : null,
center: current.type === 'DIV' ? i18n('centerkey-select') : '',
onKeyCenter,
onKeyLeft: isRandomEnabled() ? goToRandomArticle : null,
left: allowUsage() ? i18n('softkey-tips') : '',
onKeyLeft: allowUsage() ? goto.tips : null,
onKeyBackspace: !(query && current.type === 'INPUT') && onExitConfirmDialog
}, [current.type, query, isOnline])

Expand All @@ -102,3 +98,15 @@ export const Search = () => {
</div>
)
}

export const goToRandomArticle = (closePopup, skipIntro = false) => {
const lang = getAppLanguage()
const [promise] = getRandomArticleTitle(lang)

promise.then(title => {
if (closePopup) {
closePopup()
}
goto.article(lang, skipIntro ? [title, skipIntroAnchor] : title)
})
}
Loading

0 comments on commit 0321203

Please sign in to comment.