first commit
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
import BetaBadge from '../../../../frontend/js/shared/components/beta-badge'
|
||||
|
||||
describe('beta badge', function () {
|
||||
it('renders the url and tooltip text', function () {
|
||||
cy.mount(
|
||||
<BetaBadge
|
||||
link={{ href: '/foo' }}
|
||||
tooltip={{
|
||||
id: 'test-tooltip',
|
||||
text: 'This is a test',
|
||||
}}
|
||||
/>
|
||||
)
|
||||
|
||||
cy.get('a[href="/foo"]').contains('This is a test')
|
||||
})
|
||||
})
|
@@ -0,0 +1,50 @@
|
||||
import React from 'react'
|
||||
import LanguagePicker from '../../../../frontend/js/features/ui/components/bootstrap-5/language-picker'
|
||||
import getMeta from '@/utils/meta'
|
||||
import exposedSettings from '../../../../modules/admin-panel/test/frontend/js/features/user/data/exposedSettings'
|
||||
|
||||
describe('LanguagePicker', function () {
|
||||
beforeEach(function () {
|
||||
window.metaAttributesCache.set('ol-i18n', {
|
||||
currentLangCode: 'en',
|
||||
})
|
||||
window.metaAttributesCache.set('ol-footer', {
|
||||
showThinFooter: false,
|
||||
translatedLanguages: {
|
||||
en: 'English',
|
||||
fr: 'Français',
|
||||
es: 'Español',
|
||||
},
|
||||
subdomainLang: {
|
||||
en: { lngCode: 'en', url: 'overleaf.com' },
|
||||
fr: { lngCode: 'fr', url: 'fr.overleaf.com' },
|
||||
es: { lngCode: 'es', url: 'es.overleaf.com' },
|
||||
},
|
||||
})
|
||||
|
||||
Object.assign(getMeta('ol-ExposedSettings'), exposedSettings)
|
||||
})
|
||||
|
||||
it('renders the language picker with the current language', function () {
|
||||
cy.mount(<LanguagePicker showHeader />)
|
||||
cy.get('#language-picker-toggle').should('contain', 'English')
|
||||
})
|
||||
|
||||
it('opens the dropdown and lists available languages', function () {
|
||||
cy.mount(<LanguagePicker showHeader />)
|
||||
cy.get('#language-picker-toggle').click()
|
||||
|
||||
cy.get('.dropdown-menu').within(() => {
|
||||
cy.contains('English').should('exist')
|
||||
cy.contains('Français').should('exist')
|
||||
cy.contains('Español').should('exist')
|
||||
})
|
||||
})
|
||||
|
||||
it('changes the language and updates the URL when a language is selected', function () {
|
||||
cy.mount(<LanguagePicker showHeader />)
|
||||
cy.get('#language-picker-toggle').should('exist').click()
|
||||
cy.contains('Français').click()
|
||||
cy.url().should('include', 'fr.overleaf.com')
|
||||
})
|
||||
})
|
@@ -0,0 +1,30 @@
|
||||
import MaterialIcon from '@/shared/components/material-icon'
|
||||
import unfilledIconTypes from '../../../../frontend/fonts/material-symbols/unfilled-symbols.mjs'
|
||||
|
||||
const FONT_SIZE = 40
|
||||
|
||||
describe('MaterialIcon', function () {
|
||||
describe('Filled', function () {
|
||||
it('contains symbols', function () {
|
||||
cy.mount(<MaterialIcon type="home" style={{ fontSize: FONT_SIZE }} />)
|
||||
cy.get('.material-symbols').as('icon')
|
||||
cy.get('@icon')
|
||||
.invoke('width')
|
||||
.should('be.within', FONT_SIZE - 1, FONT_SIZE + 1)
|
||||
})
|
||||
})
|
||||
|
||||
describe('Unfilled', function () {
|
||||
it('Contain all unfilled symbol', function () {
|
||||
for (const type of unfilledIconTypes) {
|
||||
cy.mount(
|
||||
<MaterialIcon type={type} unfilled style={{ fontSize: FONT_SIZE }} />
|
||||
)
|
||||
cy.get('.material-symbols').as('icon')
|
||||
cy.get('@icon')
|
||||
.invoke('width')
|
||||
.should('be.within', FONT_SIZE - 1, FONT_SIZE + 1)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
345
services/web/test/frontend/components/shared/select.spec.tsx
Normal file
345
services/web/test/frontend/components/shared/select.spec.tsx
Normal file
@@ -0,0 +1,345 @@
|
||||
import { useCallback, FormEvent } from 'react'
|
||||
import OLButton from '@/features/ui/components/ol/ol-button'
|
||||
import OLForm from '@/features/ui/components/ol/ol-form'
|
||||
import OLFormControl from '@/features/ui/components/ol/ol-form-control'
|
||||
import {
|
||||
Select,
|
||||
SelectProps,
|
||||
} from '../../../../frontend/js/shared/components/select'
|
||||
|
||||
const testData = [1, 2, 3].map(index => ({
|
||||
key: index,
|
||||
value: `Demo item ${index}`,
|
||||
sub: `Subtitle ${index}`,
|
||||
}))
|
||||
|
||||
type RenderProps = Partial<SelectProps<(typeof testData)[number]>> & {
|
||||
onSubmit?: (formData: object) => void
|
||||
}
|
||||
|
||||
function render(props: RenderProps) {
|
||||
const submitHandler = (event: FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault()
|
||||
if (props.onSubmit) {
|
||||
const formData = new FormData(event.target as HTMLFormElement)
|
||||
// a plain object is more convenient to work later with assertions
|
||||
props.onSubmit(Object.fromEntries(formData.entries()))
|
||||
}
|
||||
}
|
||||
cy.mount(
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
height: '100vh',
|
||||
}}
|
||||
>
|
||||
<form onSubmit={submitHandler}>
|
||||
<Select
|
||||
items={testData}
|
||||
itemToString={x => String(x?.value)}
|
||||
label={props.label}
|
||||
name="select_control"
|
||||
defaultText={props.defaultText}
|
||||
defaultItem={props.defaultItem}
|
||||
itemToSubtitle={props.itemToSubtitle}
|
||||
itemToKey={x => String(x.key)}
|
||||
onSelectedItemChanged={props.onSelectedItemChanged}
|
||||
selected={props.selected}
|
||||
disabled={props.disabled}
|
||||
itemToDisabled={props.itemToDisabled}
|
||||
optionalLabel={props.optionalLabel}
|
||||
loading={props.loading}
|
||||
selectedIcon={props.selectedIcon}
|
||||
/>
|
||||
<button type="submit">submit</button>
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
describe('<Select />', function () {
|
||||
describe('initial rendering', function () {
|
||||
it('renders default text', function () {
|
||||
render({ defaultText: 'Choose an item' })
|
||||
cy.findByTestId('spinner').should('not.exist')
|
||||
cy.findByRole('textbox', { name: 'Choose an item' })
|
||||
})
|
||||
|
||||
it('renders default item', function () {
|
||||
render({ defaultItem: testData[2] })
|
||||
cy.findByRole('textbox', { name: 'Demo item 3' })
|
||||
})
|
||||
|
||||
it('default item takes precedence over default text', function () {
|
||||
render({ defaultText: 'Choose an item', defaultItem: testData[2] })
|
||||
cy.findByRole('textbox', { name: 'Demo item 3' })
|
||||
})
|
||||
|
||||
it('renders label', function () {
|
||||
render({
|
||||
defaultText: 'Choose an item',
|
||||
label: 'test label',
|
||||
optionalLabel: false,
|
||||
})
|
||||
cy.findByRole('textbox', { name: 'test label' })
|
||||
cy.findByRole('textbox', { name: '(Optional)' }).should('not.exist')
|
||||
})
|
||||
|
||||
it('renders optional label', function () {
|
||||
render({
|
||||
defaultText: 'Choose an item',
|
||||
label: 'test label',
|
||||
optionalLabel: true,
|
||||
})
|
||||
cy.findByRole('textbox', { name: 'test label (Optional)' })
|
||||
})
|
||||
|
||||
it('renders a spinner while loading when there is a label', function () {
|
||||
render({
|
||||
defaultText: 'Choose an item',
|
||||
label: 'test label',
|
||||
loading: true,
|
||||
})
|
||||
cy.findByTestId('spinner')
|
||||
})
|
||||
|
||||
it('does not render a spinner while loading if there is no label', function () {
|
||||
render({
|
||||
defaultText: 'Choose an item',
|
||||
loading: true,
|
||||
})
|
||||
cy.findByTestId('spinner').should('not.exist')
|
||||
})
|
||||
})
|
||||
|
||||
describe('items rendering', function () {
|
||||
it('renders all items', function () {
|
||||
render({ defaultText: 'Choose an item' })
|
||||
cy.findByRole('textbox', { name: 'Choose an item' }).click()
|
||||
|
||||
cy.findByRole('option', { name: 'Demo item 1' })
|
||||
cy.findByRole('option', { name: 'Demo item 2' })
|
||||
cy.findByRole('option', { name: 'Demo item 3' })
|
||||
})
|
||||
|
||||
it('renders subtitles', function () {
|
||||
render({
|
||||
defaultText: 'Choose an item',
|
||||
itemToSubtitle: x => String(x?.sub),
|
||||
})
|
||||
cy.findByRole('textbox', { name: 'Choose an item' }).click()
|
||||
|
||||
cy.findByRole('option', { name: 'Demo item 1 Subtitle 1' })
|
||||
cy.findByRole('option', { name: 'Demo item 2 Subtitle 2' })
|
||||
cy.findByRole('option', { name: 'Demo item 3 Subtitle 3' })
|
||||
})
|
||||
})
|
||||
|
||||
describe('item selection', function () {
|
||||
it('cannot select an item when disabled', function () {
|
||||
render({ defaultText: 'Choose an item', disabled: true })
|
||||
cy.findByRole('textbox', { name: 'Choose an item' }).click({
|
||||
force: true,
|
||||
})
|
||||
cy.findByRole('option', { name: 'Demo item 1' }).should('not.exist')
|
||||
cy.findByRole('option', { name: 'Demo item 2' }).should('not.exist')
|
||||
cy.findByRole('option', { name: 'Demo item 3' }).should('not.exist')
|
||||
cy.findByRole('textbox', { name: 'Choose an item' })
|
||||
})
|
||||
|
||||
it('renders only the selected item after selection', function () {
|
||||
render({ defaultText: 'Choose an item' })
|
||||
cy.findByRole('textbox', { name: 'Choose an item' }).click()
|
||||
|
||||
cy.findByRole('option', { name: 'Demo item 1' })
|
||||
cy.findByRole('option', { name: 'Demo item 2' })
|
||||
cy.findByRole('option', { name: 'Demo item 3' }).click()
|
||||
|
||||
cy.findByRole('textbox', { name: 'Choose an item' }).should('not.exist')
|
||||
cy.findByRole('option', { name: 'Demo item 1' }).should('not.exist')
|
||||
cy.findByRole('option', { name: 'Demo item 2' }).should('not.exist')
|
||||
cy.findByRole('textbox', { name: 'Demo item 3' })
|
||||
})
|
||||
|
||||
it('invokes callback after selection', function () {
|
||||
const selectionHandler = cy.stub().as('selectionHandler')
|
||||
|
||||
render({
|
||||
defaultText: 'Choose an item',
|
||||
onSelectedItemChanged: selectionHandler,
|
||||
})
|
||||
cy.findByRole('textbox', { name: 'Choose an item' }).click()
|
||||
cy.findByRole('option', { name: 'Demo item 2' }).click()
|
||||
|
||||
cy.get('@selectionHandler').should(
|
||||
'have.been.calledOnceWith',
|
||||
testData[1]
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when the form is submitted', function () {
|
||||
it('populates FormData with the default selected item', function () {
|
||||
const submitHandler = cy.stub().as('submitHandler')
|
||||
render({ defaultItem: testData[1], onSubmit: submitHandler })
|
||||
|
||||
cy.findByText('submit').click()
|
||||
cy.get('@submitHandler').should('have.been.calledOnceWith', {
|
||||
select_control: 'Demo item 2',
|
||||
})
|
||||
})
|
||||
|
||||
it('populates FormData with the selected item', function () {
|
||||
const submitHandler = cy.stub().as('submitHandler')
|
||||
render({ defaultItem: testData[1], onSubmit: submitHandler })
|
||||
|
||||
cy.findByRole('textbox', { name: 'Demo item 2' }).click() // open dropdown
|
||||
cy.findByText('Demo item 3').click() // choose a different item
|
||||
|
||||
cy.findByText('submit').click()
|
||||
cy.get('@submitHandler').should('have.been.calledOnceWith', {
|
||||
select_control: 'Demo item 3',
|
||||
})
|
||||
})
|
||||
|
||||
it('does not populate FormData when no item is selected', function () {
|
||||
const submitHandler = cy.stub().as('submitHandler')
|
||||
render({ defaultText: 'Choose an item', onSubmit: submitHandler })
|
||||
|
||||
cy.findByText('submit').click()
|
||||
cy.get('@submitHandler').should('have.been.calledOnceWith', {})
|
||||
})
|
||||
})
|
||||
|
||||
describe('with react-bootstrap forms', function () {
|
||||
type FormWithSelectProps = {
|
||||
onSubmit: (formData: object) => void
|
||||
}
|
||||
|
||||
const FormWithSelect = ({ onSubmit }: FormWithSelectProps) => {
|
||||
const selectComponent = useCallback(
|
||||
() => (
|
||||
<Select
|
||||
name="select_control"
|
||||
items={testData}
|
||||
defaultItem={testData[0]}
|
||||
itemToString={x => String(x?.value)}
|
||||
itemToKey={x => String(x.key)}
|
||||
/>
|
||||
),
|
||||
[]
|
||||
)
|
||||
|
||||
function handleSubmit(event: FormEvent<HTMLFormElement>) {
|
||||
event.preventDefault()
|
||||
const formData = new FormData(event.target as HTMLFormElement)
|
||||
// a plain object is more convenient to work later with assertions
|
||||
onSubmit(Object.fromEntries(formData.entries()))
|
||||
}
|
||||
|
||||
return (
|
||||
<OLForm onSubmit={handleSubmit}>
|
||||
<OLFormControl as={selectComponent} />
|
||||
<OLButton type="submit">submit</OLButton>
|
||||
</OLForm>
|
||||
)
|
||||
}
|
||||
|
||||
it('populates FormData with the selected item when the form is submitted', function () {
|
||||
const submitHandler = cy.stub().as('submitHandler')
|
||||
cy.mount(
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
height: '100vh',
|
||||
}}
|
||||
>
|
||||
<FormWithSelect onSubmit={submitHandler} />
|
||||
</div>
|
||||
)
|
||||
|
||||
cy.findByRole('textbox', { name: 'Demo item 1' }).click() // open dropdown
|
||||
cy.findByRole('option', { name: 'Demo item 3' }).click() // choose a different item
|
||||
|
||||
cy.findByText('submit').click()
|
||||
cy.get('@submitHandler').should('have.been.calledOnceWith', {
|
||||
select_control: 'Demo item 3',
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('keyboard navigation', function () {
|
||||
it('can select an item using the keyboard', function () {
|
||||
render({ defaultText: 'Choose an item' })
|
||||
cy.findByRole('textbox', { name: 'Choose an item' }).type(
|
||||
'{Enter}{downArrow}{Enter}',
|
||||
{ force: true }
|
||||
)
|
||||
cy.findByRole('textbox', { name: 'Demo item 1' }).should('exist')
|
||||
cy.findByRole('option', { name: 'Demo item 2' }).should('not.exist')
|
||||
})
|
||||
})
|
||||
|
||||
describe('selectedIcon', function () {
|
||||
it('renders a selected icon if the prop is set', function () {
|
||||
render({
|
||||
defaultText: 'Choose an item',
|
||||
selectedIcon: true,
|
||||
})
|
||||
cy.findByRole('textbox', { name: 'Choose an item' }).click()
|
||||
cy.findByRole('option', { name: 'Demo item 1' }).click()
|
||||
cy.findByRole('textbox', { name: 'Demo item 1' }).click()
|
||||
|
||||
cy.findByText('check').should('exist')
|
||||
})
|
||||
it('renders no selected icon if the prop is not set', function () {
|
||||
render({
|
||||
defaultText: 'Choose an item',
|
||||
selectedIcon: false,
|
||||
})
|
||||
cy.findByRole('textbox', { name: 'Choose an item' }).click()
|
||||
cy.findByRole('option', { name: 'Demo item 1' }).click()
|
||||
cy.findByRole('textbox', { name: 'Demo item 1' }).click()
|
||||
|
||||
cy.findByText('check').should('not.exist')
|
||||
})
|
||||
})
|
||||
|
||||
describe('itemToDisabled', function () {
|
||||
it('prevents selecting a disabled item', function () {
|
||||
render({
|
||||
defaultText: 'Choose an item',
|
||||
itemToDisabled: x => x?.key === 2,
|
||||
})
|
||||
cy.findByRole('textbox', { name: 'Choose an item' }).click()
|
||||
cy.findByRole('option', { name: 'Demo item 2' }).click({ force: true })
|
||||
// still showing other list items
|
||||
cy.findByRole('option', { name: 'Demo item 3' }).should('exist')
|
||||
cy.findByRole('option', { name: 'Demo item 1' }).click()
|
||||
// clicking an enabled item dismisses the list
|
||||
cy.findByRole('option', { name: 'Demo item 3' }).should('not.exist')
|
||||
})
|
||||
})
|
||||
|
||||
describe('selected', function () {
|
||||
it('shows the item provided in the selected prop', function () {
|
||||
render({
|
||||
defaultText: 'Choose an item',
|
||||
selected: testData[1],
|
||||
})
|
||||
cy.findByRole('textbox', { name: 'Demo item 2' }).should('exist')
|
||||
})
|
||||
|
||||
it('should show default text when selected is null', function () {
|
||||
render({
|
||||
selected: null,
|
||||
defaultText: 'Choose an item',
|
||||
})
|
||||
cy.findByRole('textbox', { name: 'Choose an item' }).should('exist')
|
||||
})
|
||||
})
|
||||
})
|
@@ -0,0 +1,228 @@
|
||||
import SplitTestBadge from '../../../../frontend/js/shared/components/split-test-badge'
|
||||
import { EditorProviders } from '../../helpers/editor-providers'
|
||||
|
||||
describe('split test badge', function () {
|
||||
it('renders an alpha badge with the url and tooltip text', function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-splitTestVariants', {
|
||||
'cypress-test': 'active',
|
||||
})
|
||||
win.metaAttributesCache.set('ol-splitTestInfo', {
|
||||
'cypress-test': {
|
||||
phase: 'alpha',
|
||||
badgeInfo: {
|
||||
url: '/alpha/participate',
|
||||
tooltipText: 'This is an alpha feature',
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders>
|
||||
<SplitTestBadge
|
||||
splitTestName="cypress-test"
|
||||
displayOnVariants={['active']}
|
||||
/>
|
||||
</EditorProviders>
|
||||
)
|
||||
|
||||
cy.findByRole('link', { name: /this is an alpha feature/i })
|
||||
.should('have.attr', 'href', '/alpha/participate')
|
||||
.find('.badge')
|
||||
.contains('α')
|
||||
})
|
||||
|
||||
it('does not render the alpha badge when user is not assigned to the variant', function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-splitTestVariants', {
|
||||
'cypress-test': 'default',
|
||||
})
|
||||
win.metaAttributesCache.set('ol-splitTestInfo', {
|
||||
'cypress-test': {
|
||||
phase: 'alpha',
|
||||
badgeInfo: {
|
||||
url: '/alpha/participate',
|
||||
tooltipText: 'This is an alpha feature',
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders>
|
||||
<SplitTestBadge
|
||||
splitTestName="cypress-test"
|
||||
displayOnVariants={['active']}
|
||||
/>
|
||||
</EditorProviders>
|
||||
)
|
||||
|
||||
cy.get('.badge').should('not.exist')
|
||||
})
|
||||
|
||||
it('renders a beta badge with the url and tooltip text', function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-splitTestVariants', {
|
||||
'cypress-test': 'active',
|
||||
})
|
||||
win.metaAttributesCache.set('ol-splitTestInfo', {
|
||||
'cypress-test': {
|
||||
phase: 'beta',
|
||||
badgeInfo: {
|
||||
url: '/beta/participate',
|
||||
tooltipText: 'This is a beta feature',
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders>
|
||||
<SplitTestBadge
|
||||
splitTestName="cypress-test"
|
||||
displayOnVariants={['active']}
|
||||
/>
|
||||
</EditorProviders>
|
||||
)
|
||||
|
||||
cy.findByRole('link', { name: /this is a beta feature/i })
|
||||
.should('have.attr', 'href', '/beta/participate')
|
||||
.find('.badge')
|
||||
.contains('β')
|
||||
})
|
||||
|
||||
it('does not render the beta badge when user is not assigned to the variant', function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-splitTestVariants', {
|
||||
'cypress-test': 'default',
|
||||
})
|
||||
win.metaAttributesCache.set('ol-splitTestInfo', {
|
||||
'cypress-test': {
|
||||
phase: 'beta',
|
||||
badgeInfo: {
|
||||
url: '/beta/participate',
|
||||
tooltipText: 'This is a beta feature',
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders>
|
||||
<SplitTestBadge
|
||||
splitTestName="cypress-test"
|
||||
displayOnVariants={['active']}
|
||||
/>
|
||||
</EditorProviders>
|
||||
)
|
||||
|
||||
cy.get('.badge').should('not.exist')
|
||||
})
|
||||
|
||||
it('renders an info badge with the url and tooltip text', function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-splitTestVariants', {
|
||||
'cypress-test': 'active',
|
||||
})
|
||||
win.metaAttributesCache.set('ol-splitTestInfo', {
|
||||
'cypress-test': {
|
||||
phase: 'release',
|
||||
badgeInfo: {
|
||||
url: '/feedback/form',
|
||||
tooltipText: 'This is a new feature',
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders>
|
||||
<SplitTestBadge
|
||||
splitTestName="cypress-test"
|
||||
displayOnVariants={['active']}
|
||||
/>
|
||||
</EditorProviders>
|
||||
)
|
||||
|
||||
cy.findByRole('link', { name: /this is a new feature/i })
|
||||
.should('have.attr', 'href', '/feedback/form')
|
||||
.find('.info-badge')
|
||||
})
|
||||
|
||||
it('does not render the info badge when user is not assigned to the variant', function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-splitTestVariants', {
|
||||
'cypress-test': 'default',
|
||||
})
|
||||
win.metaAttributesCache.set('ol-splitTestInfo', {
|
||||
'cypress-test': {
|
||||
phase: 'release',
|
||||
badgeInfo: {
|
||||
url: '/feedback/form',
|
||||
tooltipText: 'This is a new feature',
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders>
|
||||
<SplitTestBadge
|
||||
splitTestName="cypress-test"
|
||||
displayOnVariants={['active']}
|
||||
/>
|
||||
</EditorProviders>
|
||||
)
|
||||
|
||||
cy.get('.badge').should('not.exist')
|
||||
})
|
||||
|
||||
it('does not render the badge when no split test info is available', function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-splitTestVariants', {
|
||||
'cypress-test': 'active',
|
||||
})
|
||||
win.metaAttributesCache.set('ol-splitTestInfo', {})
|
||||
})
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders>
|
||||
<SplitTestBadge
|
||||
splitTestName="cypress-test"
|
||||
displayOnVariants={['active']}
|
||||
/>
|
||||
</EditorProviders>
|
||||
)
|
||||
|
||||
cy.get('.badge').should('not.exist')
|
||||
})
|
||||
|
||||
it('default badge url and text are used when not provided', function () {
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-splitTestVariants', {
|
||||
'cypress-test': 'active',
|
||||
})
|
||||
win.metaAttributesCache.set('ol-splitTestInfo', {
|
||||
'cypress-test': {
|
||||
phase: 'release',
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
cy.mount(
|
||||
<EditorProviders>
|
||||
<SplitTestBadge
|
||||
splitTestName="cypress-test"
|
||||
displayOnVariants={['active']}
|
||||
/>
|
||||
</EditorProviders>
|
||||
)
|
||||
|
||||
cy.findByRole('link', {
|
||||
name: /we are testing this new feature.*click to give feedback/i,
|
||||
})
|
||||
.should('have.attr', 'href', '/beta/participate')
|
||||
.find('.info-badge')
|
||||
})
|
||||
})
|
@@ -0,0 +1,95 @@
|
||||
import StartFreeTrialButton from '../../../../frontend/js/shared/components/start-free-trial-button'
|
||||
import getMeta from '@/utils/meta'
|
||||
|
||||
describe('start free trial button', function () {
|
||||
beforeEach(function () {
|
||||
cy.intercept('POST', '/event/paywall-prompt', {
|
||||
statusCode: 204,
|
||||
}).as('event-paywall-prompt')
|
||||
cy.intercept('POST', '/event/paywall-click', {
|
||||
statusCode: 204,
|
||||
}).as('event-paywall-click')
|
||||
|
||||
getMeta('ol-ExposedSettings').isOverleaf = true
|
||||
})
|
||||
|
||||
it('renders the button with default text', function () {
|
||||
cy.mount(<StartFreeTrialButton source="cypress-test" />)
|
||||
|
||||
cy.wait('@event-paywall-prompt')
|
||||
.its('request.body.paywall-type')
|
||||
.should('eq', 'cypress-test')
|
||||
|
||||
cy.get('button').contains('Start Free Trial!')
|
||||
})
|
||||
|
||||
it('renders the button with custom text', function () {
|
||||
cy.mount(
|
||||
<StartFreeTrialButton source="cypress-test">
|
||||
Some Custom Text
|
||||
</StartFreeTrialButton>
|
||||
)
|
||||
|
||||
cy.wait('@event-paywall-prompt')
|
||||
.its('request.body.paywall-type')
|
||||
.should('eq', 'cypress-test')
|
||||
|
||||
cy.get('button').contains('Some Custom Text')
|
||||
})
|
||||
|
||||
it('renders the button with styled button', function () {
|
||||
cy.mount(
|
||||
<StartFreeTrialButton
|
||||
source="cypress-test"
|
||||
buttonProps={{
|
||||
variant: 'danger',
|
||||
size: 'lg',
|
||||
}}
|
||||
/>
|
||||
)
|
||||
|
||||
cy.wait('@event-paywall-prompt')
|
||||
|
||||
cy.get('button.btn.btn-danger.btn-lg').contains('Start Free Trial!')
|
||||
})
|
||||
|
||||
it('renders the button with custom class', function () {
|
||||
cy.mount(
|
||||
<StartFreeTrialButton
|
||||
source="cypress-test"
|
||||
buttonProps={{ className: 'ct-test-class' }}
|
||||
/>
|
||||
)
|
||||
|
||||
cy.wait('@event-paywall-prompt')
|
||||
.its('request.body.paywall-type')
|
||||
.should('eq', 'cypress-test')
|
||||
|
||||
cy.get('.ct-test-class').contains('Start Free Trial!')
|
||||
})
|
||||
|
||||
it('calls onClick callback and opens a new tab to the subscription page on click', function () {
|
||||
const onClickStub = cy.stub()
|
||||
cy.mount(
|
||||
<StartFreeTrialButton source="cypress-test" handleClick={onClickStub} />
|
||||
)
|
||||
|
||||
cy.wait('@event-paywall-prompt')
|
||||
|
||||
cy.window().then(win => {
|
||||
cy.stub(win, 'open').as('Open')
|
||||
})
|
||||
cy.get('button.btn').contains('Start Free Trial!').click()
|
||||
|
||||
cy.wrap(null).then(() => {
|
||||
cy.wait('@event-paywall-click')
|
||||
.its('request.body.paywall-type')
|
||||
.should('eq', 'cypress-test')
|
||||
cy.get('@Open').should(
|
||||
'have.been.calledOnceWithExactly',
|
||||
'/user/subscription/choose-your-plan?itm_campaign=cypress-test'
|
||||
)
|
||||
expect(onClickStub).to.be.called
|
||||
})
|
||||
})
|
||||
})
|
@@ -0,0 +1,35 @@
|
||||
import OLTooltip from '@/features/ui/components/ol/ol-tooltip'
|
||||
|
||||
describe('<OLTooltip />', function () {
|
||||
it('calls the bound handler and blur then hides text on click', function () {
|
||||
const clickHandler = cy.stub().as('clickHandler')
|
||||
const blurHandler = cy.stub().as('blurHandler')
|
||||
const description = 'foo'
|
||||
const btnText = 'Click me!'
|
||||
|
||||
cy.mount(
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
height: '100vh',
|
||||
}}
|
||||
>
|
||||
<OLTooltip id="abc" description={description}>
|
||||
<button onClick={clickHandler} onBlur={blurHandler}>
|
||||
{btnText}
|
||||
</button>
|
||||
</OLTooltip>
|
||||
</div>
|
||||
)
|
||||
|
||||
cy.findByRole('button', { name: btnText }).as('button')
|
||||
cy.get('@button').trigger('mouseover')
|
||||
cy.findByText(description)
|
||||
cy.get('@button').click()
|
||||
cy.get('@clickHandler').should('have.been.calledOnce')
|
||||
cy.get('@blurHandler').should('have.been.calledOnce')
|
||||
cy.findByText(description).should('not.exist')
|
||||
})
|
||||
})
|
Reference in New Issue
Block a user