mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-07 20:31:06 -05:00
Merge pull request #13117 from overleaf/ii-history-react-changes-list-tests
[web] Add changes list tests GitOrigin-RevId: 5a4e1ea647d737dc761e4258002e6507c76e95a9
This commit is contained in:
parent
2760ad35fc
commit
454f8f80c2
8 changed files with 295 additions and 41 deletions
|
@ -14,20 +14,34 @@ function Changes({ pathnames, projectOps }: ChangesProps) {
|
|||
<ol className="history-version-changes">
|
||||
{pathnames.map(pathname => (
|
||||
<li key={pathname}>
|
||||
<div className="history-version-change-action">
|
||||
<div
|
||||
className="history-version-change-action"
|
||||
data-testid="history-version-change-action"
|
||||
>
|
||||
{t('file_action_edited')}
|
||||
</div>
|
||||
<div className="history-version-change-doc">{pathname}</div>
|
||||
<div
|
||||
className="history-version-change-doc"
|
||||
data-testid="history-version-change-doc"
|
||||
>
|
||||
{pathname}
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
{projectOps.map((op, index) => (
|
||||
<li key={index}>
|
||||
<div className="history-version-change-action">
|
||||
<div
|
||||
className="history-version-change-action"
|
||||
data-testid="history-version-change-action"
|
||||
>
|
||||
{op.rename && t('file_action_renamed')}
|
||||
{op.add && t('file_action_created')}
|
||||
{op.remove && t('file_action_deleted')}
|
||||
</div>
|
||||
<div className="history-version-change-doc">
|
||||
<div
|
||||
className="history-version-change-doc"
|
||||
data-testid="history-version-change-doc"
|
||||
>
|
||||
{getProjectOpDoc(op)}
|
||||
</div>
|
||||
</li>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { useTranslation } from 'react-i18next'
|
||||
import { MenuItem, MenuItemProps } from 'react-bootstrap'
|
||||
import { MenuItem } from 'react-bootstrap'
|
||||
import Icon from '../../../../../../shared/components/icon'
|
||||
import * as location from '../../../../../../shared/components/location'
|
||||
|
||||
type DownloadProps = {
|
||||
projectId: string
|
||||
|
@ -17,19 +16,12 @@ function Download({
|
|||
}: DownloadProps) {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const handleDownloadVersion = (e: React.MouseEvent<MenuItemProps>) => {
|
||||
e.preventDefault()
|
||||
closeDropdown()
|
||||
const event = e as typeof e & { target: HTMLAnchorElement }
|
||||
location.assign(event.target.href)
|
||||
}
|
||||
|
||||
return (
|
||||
<MenuItem
|
||||
href={`/project/${projectId}/version/${version}/zip`}
|
||||
target="_blank"
|
||||
download={`${projectId}_v${version}.zip`}
|
||||
rel="noreferrer"
|
||||
onClick={handleDownloadVersion}
|
||||
onClick={closeDropdown}
|
||||
{...props}
|
||||
>
|
||||
<Icon type="cloud-download" fw /> {t('history_download_this_version')}
|
||||
|
|
|
@ -38,6 +38,7 @@ function HistoryVersionDetails({
|
|||
'history-version-selectable': selectable,
|
||||
})}
|
||||
data-testid="history-version-details"
|
||||
data-selected={selected}
|
||||
onClick={selectable ? handleSelect : undefined}
|
||||
>
|
||||
{children}
|
||||
|
|
|
@ -66,7 +66,10 @@ function HistoryVersion({
|
|||
selectable={selectable}
|
||||
>
|
||||
<div className="history-version-main-details">
|
||||
<time className="history-version-metadata-time">
|
||||
<time
|
||||
className="history-version-metadata-time"
|
||||
data-testid="history-version-metadata-time"
|
||||
>
|
||||
<b>{formatTime(update.meta.end_ts, 'Do MMMM, h:mm a')}</b>
|
||||
</time>
|
||||
{orderedLabels.map(label => (
|
||||
|
|
|
@ -76,7 +76,10 @@ function LabelListItem({
|
|||
currentUserId={currentUserId}
|
||||
label={label}
|
||||
/>
|
||||
<time className="history-version-metadata-time">
|
||||
<time
|
||||
className="history-version-metadata-time"
|
||||
data-testid="history-version-metadata-time"
|
||||
>
|
||||
{formatTime(label.created_at, 'Do MMMM, h:mm a')}
|
||||
</time>
|
||||
{!isPseudoLabel(label) && (
|
||||
|
|
|
@ -15,7 +15,10 @@ function MetadataUsersList({
|
|||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<ol className="history-version-metadata-users">
|
||||
<ol
|
||||
className="history-version-metadata-users"
|
||||
data-testid="history-version-metadata-users"
|
||||
>
|
||||
{users.map((user, index) => (
|
||||
<li key={index}>
|
||||
<UserNameWithColoredBadge user={user} currentUserId={currentUserId} />
|
||||
|
|
|
@ -9,6 +9,10 @@ import {
|
|||
import { HistoryProvider } from '../../../../../frontend/js/features/history/context/history-context'
|
||||
import { updates } from '../fixtures/updates'
|
||||
import { labels } from '../fixtures/labels'
|
||||
import {
|
||||
formatTime,
|
||||
relativeDate,
|
||||
} from '../../../../../frontend/js/features/utils/format-date'
|
||||
|
||||
const mountWithEditorProviders = (
|
||||
component: React.ReactNode,
|
||||
|
@ -27,6 +31,28 @@ const mountWithEditorProviders = (
|
|||
}
|
||||
|
||||
describe('change list', function () {
|
||||
const scope = {
|
||||
ui: { view: 'history', pdfLayout: 'sideBySide', chatOpen: true },
|
||||
}
|
||||
|
||||
const waitForData = () => {
|
||||
cy.wait('@updates')
|
||||
cy.wait('@labels')
|
||||
cy.wait('@diff')
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
cy.intercept('GET', '/project/*/updates*', {
|
||||
body: updates,
|
||||
}).as('updates')
|
||||
cy.intercept('GET', '/project/*/labels', {
|
||||
body: labels,
|
||||
}).as('labels')
|
||||
cy.intercept('GET', '/project/*/filetree/diff*', {
|
||||
body: { diff: [{ pathname: 'main.tex' }, { pathname: 'name.tex' }] },
|
||||
}).as('diff')
|
||||
})
|
||||
|
||||
describe('toggle switch', function () {
|
||||
it('renders switch buttons', function () {
|
||||
mountWithEditorProviders(
|
||||
|
@ -61,28 +87,6 @@ describe('change list', function () {
|
|||
})
|
||||
|
||||
describe('tags', function () {
|
||||
const scope = {
|
||||
ui: { view: 'history', pdfLayout: 'sideBySide', chatOpen: true },
|
||||
}
|
||||
|
||||
const waitForData = () => {
|
||||
cy.wait('@updates')
|
||||
cy.wait('@labels')
|
||||
cy.wait('@diff')
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
cy.intercept('GET', '/project/*/updates*', {
|
||||
body: updates,
|
||||
}).as('updates')
|
||||
cy.intercept('GET', '/project/*/labels', {
|
||||
body: labels,
|
||||
}).as('labels')
|
||||
cy.intercept('GET', '/project/*/filetree/diff*', {
|
||||
body: { diff: [{ pathname: 'main.tex' }, { pathname: 'name.tex' }] },
|
||||
}).as('diff')
|
||||
})
|
||||
|
||||
it('renders tags', function () {
|
||||
mountWithEditorProviders(<ChangeList />, scope, {
|
||||
user: {
|
||||
|
@ -215,6 +219,234 @@ describe('change list', function () {
|
|||
cy.wait('@delete')
|
||||
cy.findByText(labelToDelete).should('not.exist')
|
||||
})
|
||||
|
||||
it('verifies that selecting the same list item will not trigger a new diff', function () {
|
||||
mountWithEditorProviders(<ChangeList />, scope, {
|
||||
user: {
|
||||
id: USER_ID,
|
||||
email: USER_EMAIL,
|
||||
isAdmin: true,
|
||||
},
|
||||
})
|
||||
waitForData()
|
||||
|
||||
const stub = cy.stub().as('diffStub')
|
||||
cy.intercept('GET', '/project/*/filetree/diff*', stub).as('diff')
|
||||
|
||||
cy.findAllByTestId('history-version-details').eq(1).as('details')
|
||||
cy.get('@details').click() // 1st click
|
||||
cy.wait('@diff')
|
||||
cy.get('@details').click() // 2nd click
|
||||
cy.get('@diffStub').should('have.been.calledOnce')
|
||||
})
|
||||
})
|
||||
|
||||
describe('all history', function () {
|
||||
beforeEach(function () {
|
||||
mountWithEditorProviders(<ChangeList />, scope, {
|
||||
user: {
|
||||
id: USER_ID,
|
||||
email: USER_EMAIL,
|
||||
isAdmin: true,
|
||||
},
|
||||
})
|
||||
waitForData()
|
||||
})
|
||||
|
||||
it('shows grouped versions date', function () {
|
||||
cy.findByText(relativeDate(updates.updates[0].meta.end_ts))
|
||||
cy.findByText(relativeDate(updates.updates[1].meta.end_ts))
|
||||
})
|
||||
|
||||
it('shows the date of the version', function () {
|
||||
cy.findAllByTestId('history-version-details')
|
||||
.eq(0)
|
||||
.within(() => {
|
||||
cy.findByTestId('history-version-metadata-time').should(
|
||||
'have.text',
|
||||
formatTime(updates.updates[0].meta.end_ts, 'Do MMMM, h:mm a')
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
it('shows change action', function () {
|
||||
cy.findAllByTestId('history-version-details')
|
||||
.eq(0)
|
||||
.within(() => {
|
||||
cy.findByTestId('history-version-change-action').should(
|
||||
'have.text',
|
||||
'Created'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
it('shows changed document name', function () {
|
||||
cy.findAllByTestId('history-version-details')
|
||||
.eq(1)
|
||||
.within(() => {
|
||||
cy.findByTestId('history-version-change-doc').should(
|
||||
'have.text',
|
||||
updates.updates[1].pathnames[0]
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
it('shows users', function () {
|
||||
cy.findAllByTestId('history-version-details')
|
||||
.eq(0)
|
||||
.within(() => {
|
||||
cy.findByTestId('history-version-metadata-users')
|
||||
.should('contain.text', 'You')
|
||||
.and('contain.text', updates.updates[0].meta.users[1].first_name)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('labels only', function () {
|
||||
beforeEach(function () {
|
||||
mountWithEditorProviders(<ChangeList />, scope, {
|
||||
user: {
|
||||
id: USER_ID,
|
||||
email: USER_EMAIL,
|
||||
isAdmin: true,
|
||||
},
|
||||
})
|
||||
waitForData()
|
||||
cy.findByLabelText(/labels/i).click({ force: true })
|
||||
})
|
||||
|
||||
it('does not show the dropdown menu item for adding new labels', function () {
|
||||
cy.findAllByTestId('history-version-details')
|
||||
.eq(1)
|
||||
.within(() => {
|
||||
cy.findByRole('button', { name: /more actions/i }).click()
|
||||
cy.findByRole('menu').within(() => {
|
||||
cy.findByRole('menuitem', {
|
||||
name: /label this version/i,
|
||||
}).should('not.exist')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('resets from compare to view mode when switching tabs', function () {
|
||||
cy.findAllByTestId('history-version-details')
|
||||
.eq(1)
|
||||
.within(() => {
|
||||
cy.findByRole('button', { name: /more actions/i }).click()
|
||||
cy.findByRole('menu').within(() => {
|
||||
cy.findByRole('menuitem', {
|
||||
name: /compare to selected version/i,
|
||||
}).click()
|
||||
})
|
||||
})
|
||||
cy.wait('@diff')
|
||||
cy.findByLabelText(/all history/i).click({ force: true })
|
||||
cy.findAllByTestId('history-version-details').should($versions => {
|
||||
const [first, ...rest] = Array.from($versions)
|
||||
expect(first.dataset.selected === 'true').to.be.true
|
||||
expect(rest.every(version => version.dataset.selected === 'false')).to
|
||||
.be.true
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('dropdown', function () {
|
||||
beforeEach(function () {
|
||||
mountWithEditorProviders(<ChangeList />, scope, {
|
||||
user: {
|
||||
id: USER_ID,
|
||||
email: USER_EMAIL,
|
||||
isAdmin: true,
|
||||
},
|
||||
})
|
||||
waitForData()
|
||||
})
|
||||
|
||||
it('adds badge/label', function () {
|
||||
cy.findAllByTestId('history-version-details').eq(1).as('version')
|
||||
cy.get('@version').within(() => {
|
||||
cy.findByRole('button', { name: /more actions/i }).click()
|
||||
cy.findByRole('menu').within(() => {
|
||||
cy.findByRole('menuitem', {
|
||||
name: /label this version/i,
|
||||
}).click()
|
||||
})
|
||||
})
|
||||
cy.findByRole('dialog').as('modal')
|
||||
cy.intercept('POST', '/project/*/labels', req => {
|
||||
req.reply(200, {
|
||||
id: '64633ee158e9ef7da614c000',
|
||||
comment: req.body.comment,
|
||||
version: req.body.version,
|
||||
user_id: USER_ID,
|
||||
created_at: '2023-05-16T08:29:21.250Z',
|
||||
user_display_name: 'john.doe',
|
||||
})
|
||||
}).as('addLabel')
|
||||
const newLabel = 'my new label'
|
||||
cy.get('@modal').within(() => {
|
||||
cy.findByRole('heading', { name: /add label/i })
|
||||
cy.findByRole('button', { name: /cancel/i })
|
||||
cy.findByRole('button', { name: /add label/i }).should('be.disabled')
|
||||
cy.findByPlaceholderText(/new label name/i).as('input')
|
||||
cy.get('@input').type(newLabel)
|
||||
cy.findByRole('button', { name: /add label/i }).should('be.enabled')
|
||||
cy.get('@input').type('{enter}')
|
||||
})
|
||||
cy.wait('@addLabel')
|
||||
cy.get('@version').within(() => {
|
||||
cy.findAllByTestId('history-version-badge').should($badges => {
|
||||
const includes = Array.from($badges).some(badge =>
|
||||
badge.textContent?.includes(newLabel)
|
||||
)
|
||||
expect(includes).to.be.true
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('downloads version', function () {
|
||||
cy.intercept('GET', '/project/*/version/*/zip', { statusCode: 200 }).as(
|
||||
'download'
|
||||
)
|
||||
cy.findAllByTestId('history-version-details')
|
||||
.eq(0)
|
||||
.within(() => {
|
||||
cy.findByRole('button', { name: /more actions/i }).click()
|
||||
cy.findByRole('menu').within(() => {
|
||||
cy.findByRole('menuitem', {
|
||||
name: /download this version/i,
|
||||
}).click()
|
||||
})
|
||||
})
|
||||
cy.wait('@download')
|
||||
})
|
||||
|
||||
it('compares versions', function () {
|
||||
cy.findAllByTestId('history-version-details').should($versions => {
|
||||
const [first, ...rest] = Array.from($versions)
|
||||
expect(first).to.have.attr('data-selected', 'true')
|
||||
rest.forEach(version =>
|
||||
expect(version).to.have.attr('data-selected', 'false')
|
||||
)
|
||||
})
|
||||
|
||||
cy.intercept('GET', '/project/*/filetree/diff*', { statusCode: 200 }).as(
|
||||
'compareDiff'
|
||||
)
|
||||
|
||||
cy.findAllByTestId('history-version-details')
|
||||
.last()
|
||||
.within(() => {
|
||||
cy.findByRole('button', { name: /more actions/i }).click()
|
||||
cy.findByRole('menu').within(() => {
|
||||
cy.findByRole('menuitem', {
|
||||
name: /compare to selected version/i,
|
||||
}).click()
|
||||
})
|
||||
})
|
||||
|
||||
cy.wait('@compareDiff')
|
||||
})
|
||||
})
|
||||
|
||||
describe('paywall', function () {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { USER_ID } from '../../../helpers/editor-providers'
|
||||
import { USER_ID, USER_EMAIL } from '../../../helpers/editor-providers'
|
||||
|
||||
export const updates = {
|
||||
updates: [
|
||||
|
@ -7,6 +7,12 @@ export const updates = {
|
|||
toV: 4,
|
||||
meta: {
|
||||
users: [
|
||||
{
|
||||
first_name: 'testuser',
|
||||
last_name: '',
|
||||
email: USER_EMAIL,
|
||||
id: USER_ID,
|
||||
},
|
||||
{
|
||||
first_name: 'john.doe',
|
||||
last_name: '',
|
||||
|
|
Loading…
Reference in a new issue