feat: v4.0.0 (#1016)

Co-authored-by: Denys Konovalov <kontakt@denyskon.de>
Co-authored-by: Mathieu COSYNS <64072917+Mathieu-COSYNS@users.noreply.github.com>
This commit is contained in:
Daniel Lautzenheiser
2024-01-03 15:14:09 -05:00
committed by GitHub
parent 682576ffc4
commit 799c7e6936
732 changed files with 48477 additions and 10886 deletions

View File

@ -0,0 +1,30 @@
import fixture from '../common/editorial_workflow';
import * as specUtils from '../common/spec_utils';
import { entry1, entry2, entry3 } from '../common/entries';
const backend = 'bitbucket';
describe('BitBucket Backend Editorial Workflow', () => {
let taskResult = { data: {} };
before(() => {
specUtils.before(taskResult, { publish_mode: 'editorial_workflow' }, backend);
});
after(() => {
specUtils.after(taskResult, backend);
});
beforeEach(() => {
specUtils.beforeEach(taskResult, backend);
});
afterEach(() => {
specUtils.afterEach(taskResult, backend);
});
fixture({
entries: [entry1, entry2, entry3],
getUser: () => taskResult.data.user,
});
});

View File

@ -0,0 +1,31 @@
import fixture from '../common/editorial_workflow';
import * as specUtils from '../common/spec_utils';
import { entry1, entry2, entry3 } from '../common/entries';
const backend = 'git-gateway';
const provider = 'github';
describe('Git Gateway (GitHub) Backend Editorial Workflow', () => {
let taskResult = { data: {} };
before(() => {
specUtils.before(taskResult, { publish_mode: 'editorial_workflow', provider }, backend);
});
after(() => {
specUtils.after(taskResult, backend);
});
beforeEach(() => {
specUtils.beforeEach(taskResult, backend);
});
afterEach(() => {
specUtils.afterEach(taskResult, backend);
});
fixture({
entries: [entry1, entry2, entry3],
getUser: () => taskResult.data.user,
});
});

View File

@ -0,0 +1,31 @@
import fixture from '../common/editorial_workflow';
import * as specUtils from '../common/spec_utils';
import { entry1, entry2, entry3 } from '../common/entries';
const backend = 'git-gateway';
const provider = 'gitlab';
describe('Git Gateway (GitLab) Backend Editorial Workflow', () => {
let taskResult = { data: {} };
before(() => {
specUtils.before(taskResult, { publish_mode: 'editorial_workflow', provider }, backend);
});
after(() => {
specUtils.after(taskResult, backend);
});
beforeEach(() => {
specUtils.beforeEach(taskResult, backend);
});
afterEach(() => {
specUtils.afterEach(taskResult, backend);
});
fixture({
entries: [entry1, entry2, entry3],
getUser: () => taskResult.data.user,
});
});

View File

@ -0,0 +1,37 @@
import fixture from '../common/editorial_workflow';
import * as specUtils from '../common/spec_utils';
import { entry1, entry2, entry3 } from '../common/entries';
const backend = 'github';
describe('Github Backend Editorial Workflow - GraphQL API', () => {
const taskResult = { data: {} };
before(() => {
specUtils.before(
taskResult,
{
backend: { use_graphql: true, open_authoring: false },
publish_mode: 'editorial_workflow',
},
backend,
);
});
after(() => {
specUtils.after(taskResult, backend);
});
beforeEach(() => {
specUtils.beforeEach(taskResult, backend);
});
afterEach(() => {
specUtils.afterEach(taskResult, backend);
});
fixture({
entries: [entry1, entry2, entry3],
getUser: () => taskResult.data.user,
});
});

View File

@ -0,0 +1,38 @@
import fixture from '../common/open_authoring';
import * as specUtils from '../common/spec_utils';
import { entry1, entry2, entry3 } from '../common/entries';
const backend = 'github';
describe('Github Backend Editorial Workflow - GraphQL API - Open Authoring', () => {
const taskResult = { data: {} };
before(() => {
specUtils.before(
taskResult,
{
backend: { use_graphql: true, open_authoring: true },
publish_mode: 'editorial_workflow',
},
backend,
);
});
after(() => {
specUtils.after(taskResult, backend);
});
beforeEach(() => {
specUtils.beforeEach(taskResult, backend);
});
afterEach(() => {
specUtils.afterEach(taskResult, backend);
});
fixture({
entries: [entry1, entry2, entry3],
getUser: () => taskResult.data.user,
getForkUser: () => taskResult.data.forkUser,
});
});

View File

@ -0,0 +1,37 @@
import fixture from '../common/editorial_workflow';
import * as specUtils from '../common/spec_utils';
import { entry1, entry2, entry3 } from '../common/entries';
const backend = 'github';
describe('Github Backend Editorial Workflow - REST API', () => {
let taskResult = { data: {} };
before(() => {
specUtils.before(
taskResult,
{
backend: { use_graphql: false, open_authoring: false },
publish_mode: 'editorial_workflow',
},
backend,
);
});
after(() => {
specUtils.after(taskResult, backend);
});
beforeEach(() => {
specUtils.beforeEach(taskResult, backend);
});
afterEach(() => {
specUtils.afterEach(taskResult, backend);
});
fixture({
entries: [entry1, entry2, entry3],
getUser: () => taskResult.data.user,
});
});

View File

@ -0,0 +1,38 @@
import fixture from '../common/open_authoring';
import * as specUtils from '../common/spec_utils';
import { entry1, entry2, entry3 } from '../common/entries';
const backend = 'github';
describe('Github Backend Editorial Workflow - REST API - Open Authoring', () => {
let taskResult = { data: {} };
before(() => {
specUtils.before(
taskResult,
{
backend: { use_graphql: false, open_authoring: true },
publish_mode: 'editorial_workflow',
},
backend,
);
});
after(() => {
specUtils.after(taskResult, backend);
});
beforeEach(() => {
specUtils.beforeEach(taskResult, backend);
});
afterEach(() => {
specUtils.afterEach(taskResult, backend);
});
fixture({
entries: [entry1, entry2, entry3],
getUser: () => taskResult.data.user,
getForkUser: () => taskResult.data.forkUser,
});
});

View File

@ -0,0 +1,36 @@
import fixture from '../common/editorial_workflow';
import * as specUtils from '../common/spec_utils';
import { entry1, entry2, entry3 } from '../common/entries';
const backend = 'gitlab';
describe('GitLab Backend Editorial Workflow', () => {
let taskResult = { data: {} };
before(() => {
specUtils.before(taskResult, { publish_mode: 'editorial_workflow' }, backend);
});
after(() => {
specUtils.after(taskResult, backend);
});
beforeEach(() => {
if (
Cypress.mocha.getRunner().suite.ctx.currentTest.title ===
'can change status on and publish multiple entries'
) {
Cypress.mocha.getRunner().suite.ctx.currentTest.skip();
}
specUtils.beforeEach(taskResult, backend);
});
afterEach(() => {
specUtils.afterEach(taskResult, backend);
});
fixture({
entries: [entry1, entry2, entry3],
getUser: () => taskResult.data.user,
});
});

View File

@ -0,0 +1,32 @@
import fixture from '../common/editorial_workflow';
import * as specUtils from '../common/spec_utils';
import { entry1, entry2, entry3 } from '../common/entries';
const backend = 'proxy';
const mode = 'git';
describe.skip(`Proxy Backend Editorial Workflow - '${mode}' mode`, () => {
let taskResult = { data: {} };
before(() => {
specUtils.before(taskResult, { publish_mode: 'editorial_workflow', mode }, backend);
Cypress.config('defaultCommandTimeout', 5 * 1000);
});
after(() => {
specUtils.after(taskResult, backend);
});
beforeEach(() => {
specUtils.beforeEach(taskResult, backend);
});
afterEach(() => {
specUtils.afterEach(taskResult, backend);
});
fixture({
entries: [entry1, entry2, entry3],
getUser: () => taskResult.data.user,
});
});

View File

@ -0,0 +1,54 @@
import {
login,
validateObjectFieldsAndExit,
validateNestedObjectFieldsAndExit,
validateListFieldsAndExit,
validateNestedListFieldsAndExit,
} from '../../utils/steps';
import { setting1, setting2 } from '../../utils/constants';
describe('Test Backend Editorial Workflow', () => {
after(() => {
cy.task('teardownBackend', { backend: 'test' });
});
before(() => {
Cypress.config('defaultCommandTimeout', 4000);
});
beforeEach(() => {
cy.task('setupBackend', { backend: 'test' });
});
it('can validate object fields', () => {
login({ editorialWorkflow: true });
cy.contains('a', 'Posts').click();
validateObjectFieldsAndExit(setting1);
});
it('can validate fields nested in an object field', () => {
login({ editorialWorkflow: true });
cy.contains('a', 'Posts').click();
validateNestedObjectFieldsAndExit(setting1);
});
it('can validate list fields', () => {
login({ editorialWorkflow: true });
cy.contains('a', 'Posts').click();
validateListFieldsAndExit(setting2);
});
it('can validate deeply nested list fields', () => {
login({ editorialWorkflow: true });
cy.contains('a', 'Posts').click();
validateNestedListFieldsAndExit(setting2);
});
});

View File

@ -0,0 +1,38 @@
import fixture from '../common/i18n_editorial_workflow_spec';
const backend = 'test';
describe(`I18N Test Backend Editorial Workflow`, () => {
const taskResult = { data: {} };
before(() => {
Cypress.config('defaultCommandTimeout', 4000);
cy.task('setupBackend', {
backend,
options: {
publish_mode: 'editorial_workflow',
i18n: {
locales: ['en', 'de', 'fr'],
},
collections: [
{
folder: 'content/i18n',
i18n: true,
fields: [{ i18n: true }, {}, { i18n: 'duplicate' }],
},
],
},
});
});
after(() => {
cy.task('teardownBackend', { backend });
});
const entry = {
Title: 'first title',
Body: 'first body',
};
fixture({ entry, getUser: () => taskResult.data.user });
});

View File

@ -0,0 +1,148 @@
import * as specUtils from '../common/spec_utils';
import { login } from '../../utils/steps';
import { createEntryTranslateAndPublish } from '../common/i18n';
const backend = 'proxy';
const mode = 'fs';
const expectedEnContent = `---
template: post
title: first title
date: 1970-01-01T00:00:00.000Z
description: first description
category: first category
tags:
- tag1
---
`;
const expectedDeContent = `---
title: de
date: 1970-01-01T00:00:00.000Z
---
`;
const expectedFrContent = `---
title: fr
date: 1970-01-01T00:00:00.000Z
---
`;
const contentSingleFile = `---
en:
template: post
date: 1970-01-01T00:00:00.000Z
title: first title
body: first body
description: first description
category: first category
tags:
- tag1
de:
date: 1970-01-01T00:00:00.000Z
title: de
fr:
date: 1970-01-01T00:00:00.000Z
title: fr
---
`;
describe(`I18N Proxy Backend Simple Workflow - '${mode}' mode`, () => {
const taskResult = { data: {} };
const entry = {
Title: 'first title',
Body: 'first body',
Description: 'first description',
Category: 'first category',
Tags: 'tag1',
};
before(() => {
specUtils.before(
taskResult,
{
mode,
publish_mode: 'simple',
i18n: {
locales: ['en', 'de', 'fr'],
},
collections: [{ i18n: true, fields: [{}, { i18n: true }, {}, { i18n: 'duplicate' }] }],
},
backend,
);
Cypress.config('taskTimeout', 15 * 1000);
Cypress.config('defaultCommandTimeout', 5 * 1000);
});
after(() => {
specUtils.after(taskResult, backend);
});
beforeEach(() => {
specUtils.beforeEach(taskResult, backend);
});
afterEach(() => {
specUtils.afterEach(taskResult, backend);
});
it('can create entry with translation in locale_folders mode', () => {
cy.task('updateConfig', { i18n: { structure: 'multiple_folders' } });
login({ user: taskResult.data.user });
createEntryTranslateAndPublish(entry);
cy.readFile(`${taskResult.data.tempDir}/content/posts/en/1970-01-01-first-title.md`).should(
'contain',
expectedEnContent,
);
cy.readFile(`${taskResult.data.tempDir}/content/posts/de/1970-01-01-first-title.md`).should(
'eq',
expectedDeContent,
);
cy.readFile(`${taskResult.data.tempDir}/content/posts/fr/1970-01-01-first-title.md`).should(
'eq',
expectedFrContent,
);
});
it('can create entry with translation in single_file mode', () => {
cy.task('updateConfig', { i18n: { structure: 'multiple_files' } });
login({ user: taskResult.data.user });
createEntryTranslateAndPublish(entry);
cy.readFile(`${taskResult.data.tempDir}/content/posts/1970-01-01-first-title.en.md`).should(
'contain',
expectedEnContent,
);
cy.readFile(`${taskResult.data.tempDir}/content/posts/1970-01-01-first-title.de.md`).should(
'eq',
expectedDeContent,
);
cy.readFile(`${taskResult.data.tempDir}/content/posts/1970-01-01-first-title.fr.md`).should(
'eq',
expectedFrContent,
);
});
it('can create entry with translation in locale_file_extensions mode', () => {
cy.task('updateConfig', { i18n: { structure: 'single_file' } });
login({ user: taskResult.data.user });
createEntryTranslateAndPublish(entry);
cy.readFile(`${taskResult.data.tempDir}/content/posts/1970-01-01-first-title.md`).should(
'eq',
contentSingleFile,
);
});
});

View File

@ -0,0 +1,76 @@
describe('Markdown widget', () => {
before(() => {
Cypress.config('defaultCommandTimeout', 4000);
cy.task('setupBackend', { backend: 'test' });
});
beforeEach(() => {
cy.loginAndNewPost();
cy.clearMarkdownEditorContent();
});
after(() => {
cy.task('teardownBackend', { backend: 'test' });
});
// describe('pressing backspace', () => {
it('sets non-default block to default when empty', () => {
cy.focused().clickHeadingOneButton().backspace().confirmMarkdownEditorContent(`
<p></p>
`);
});
it('moves to previous block when no character left to delete', () => {
cy.focused().type('foo').enter().clickHeadingOneButton().type('a').backspace({ times: 2 })
.confirmMarkdownEditorContent(`
<p>foo</p>
`);
});
it('does nothing at start of first block in document when non-empty and non-default', () => {
cy.focused().clickHeadingOneButton().type('foo').setCursorBefore('foo').backspace({ times: 4 })
.confirmMarkdownEditorContent(`
<h1>foo</h1>
`);
});
it('deletes individual characters in middle of non-empty non-default block in document', () => {
cy.focused().clickHeadingOneButton().type('foo').setCursorAfter('fo').backspace({ times: 3 })
.confirmMarkdownEditorContent(`
<h1>o</h1>
`);
});
it('at beginning of non-first block, moves default block content to previous block', () => {
cy
.focused()
.clickHeadingOneButton()
.type('foo')
.enter()
.type('bar')
.setCursorBefore('bar')
.backspace().confirmMarkdownEditorContent(`
<h1>foobar</h1>
`);
});
it('at beginning of non-first block, moves non-default block content to previous block', () => {
cy
.focused()
.type('foo')
.enter()
.clickHeadingOneButton()
.type('bar')
.enter()
.clickHeadingTwoButton()
.type('baz')
.setCursorBefore('baz')
.backspace()
.confirmMarkdownEditorContent(
`
<p>foo</p>
<h1>barbaz</h1>
`,
)
.setCursorBefore('bar')
.backspace().confirmMarkdownEditorContent(`
<p>foobarbaz</p>
`);
// });
});
});

View File

@ -0,0 +1,134 @@
import { oneLineTrim, stripIndent } from 'common-tags';
describe('Markdown widget code block', () => {
before(() => {
Cypress.config('defaultCommandTimeout', 4000);
cy.task('setupBackend', { backend: 'test' });
});
beforeEach(() => {
cy.loginAndNewPost();
cy.clearMarkdownEditorContent();
});
after(() => {
cy.task('teardownBackend', { backend: 'test' });
});
describe('code block', () => {
it('outputs code', () => {
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy
.insertCodeBlock()
.type('foo')
.enter()
.type('bar')
.confirmMarkdownEditorContent(
`
${codeBlock(`
foo
bar
`)}
`,
)
.wait(500)
.clickModeToggle().confirmMarkdownEditorContent(`
${codeBlockRaw(`
foo
bar
`)}
`);
});
});
});
function codeBlockRaw(content) {
return ['```', ...stripIndent(content).split('\n'), '```']
.map(
line => oneLineTrim`
<div>
<span>
<span>
<span>${line}</span>
</span>
</span>
</div>
`,
)
.join('');
}
function codeBlock(content) {
const lines = stripIndent(content)
.split('\n')
.map(
(line, idx) => `
<div>
<div>
<div>${idx + 1}</div>
</div>
<pre><span>${line}</span></pre>
</div>
`,
)
.join('');
return oneLineTrim`
<div>
<div></div>
<div>
<div><label>Code Block </label>
<div><button><span><svg>
<path></path>
</svg></span></button>
<div>
<div>
<div><textarea></textarea></div>
<div>
<div></div>
</div>
<div>
<div></div>
</div>
<div></div>
<div></div>
<div>
<div>
<div>
<div>
<div>
<div>
<pre><span>xxxxxxxxxx</span></pre>
</div>
<div></div>
<div></div>
<div>
<div> </div>
</div>
<div>
${lines}
</div>
</div>
</div>
</div>
</div>
<div></div>
<div>
<div></div>
</div>
</div>
</div>
</div>
</div>
</div>
<div>
<span>
<span>
<span></span>
</span>
</span>
</div>
</div>
<div></div>
</div>
`;
}

View File

@ -0,0 +1,80 @@
describe('Markdown widget breaks', () => {
before(() => {
Cypress.config('defaultCommandTimeout', 4000);
cy.task('setupBackend', { backend: 'test' });
});
beforeEach(() => {
cy.loginAndNewPost();
cy.clearMarkdownEditorContent();
});
after(() => {
cy.task('teardownBackend', { backend: 'test' });
});
describe('pressing enter', () => {
it('creates new default block from empty block', () => {
cy.focused().enter().confirmMarkdownEditorContent(`
<p></p>
<p></p>
`);
});
it('creates new default block when selection collapsed at end of block', () => {
cy.focused().type('foo').enter().confirmMarkdownEditorContent(`
<p>foo</p>
<p></p>
`);
});
it('creates new default block when selection collapsed at end of non-default block', () => {
cy.clickHeadingOneButton().type('foo').enter().confirmMarkdownEditorContent(`
<h1>foo</h1>
<p></p>
`);
});
it('creates new default block when selection collapsed in empty non-default block', () => {
cy.clickHeadingOneButton().enter().confirmMarkdownEditorContent(`
<h1></h1>
<p></p>
`);
});
it('splits block into two same-type blocks when collapsed selection at block start', () => {
cy.clickHeadingOneButton().type('foo').setCursorBefore('foo').enter()
.confirmMarkdownEditorContent(`
<h1></h1>
<h1>foo</h1>
`);
});
it('splits block into two same-type blocks when collapsed in middle of selection at block start', () => {
cy.clickHeadingOneButton().type('foo').setCursorBefore('oo').enter()
.confirmMarkdownEditorContent(`
<h1>f</h1>
<h1>oo</h1>
`);
});
it('deletes selected content and splits to same-type block when selection is expanded', () => {
cy.clickHeadingOneButton().type('foo bar').setSelection('o b').enter()
.confirmMarkdownEditorContent(`
<h1>fo</h1>
<h1>ar</h1>
`);
});
});
describe('pressing shift+enter', () => {
it('creates line break', () => {
cy.focused().enter({ shift: true }).confirmMarkdownEditorContent(`
<p>
</p>
`);
});
it('creates consecutive line break', () => {
cy.focused().enter({ shift: true, times: 4 }).confirmMarkdownEditorContent(`
<p>
</p>
`);
});
});
});

View File

@ -0,0 +1,109 @@
import { HOT_KEY_MAP } from '../../utils/constants';
const headingNumberToWord = ['', 'one', 'two', 'three', 'four', 'five', 'six'];
const isMac = Cypress.platform === 'darwin';
const modifierKey = isMac ? '{meta}' : '{ctrl}';
// eslint-disable-next-line func-style
const replaceMod = str => str.replace(/mod\+/g, modifierKey).replace(/shift\+/g, '{shift}');
describe('Markdown widget hotkeys', () => {
describe('hot keys', () => {
before(() => {
Cypress.config('defaultCommandTimeout', 4000);
cy.task('setupBackend', { backend: 'test' });
});
beforeEach(() => {
cy.loginAndNewPost();
cy.clearMarkdownEditorContent();
cy.focused().type('foo').setSelection('foo').as('selection');
});
after(() => {
cy.task('teardownBackend', { backend: 'test' });
});
describe('bold', () => {
it('pressing mod+b bolds the text', () => {
cy.get('@selection')
.type(replaceMod(HOT_KEY_MAP['bold']))
.confirmMarkdownEditorContent(
`
<p>
<strong>foo</strong>
</p>
`,
)
.type(replaceMod(HOT_KEY_MAP['bold']));
});
});
describe('italic', () => {
it('pressing mod+i italicizes the text', () => {
cy.get('@selection')
.type(replaceMod(HOT_KEY_MAP['italic']))
.confirmMarkdownEditorContent(
`
<p>
<em>foo</em>
</p>
`,
)
.type(replaceMod(HOT_KEY_MAP['italic']));
});
});
describe('strikethrough', () => {
it('pressing mod+shift+s displays a strike through the text', () => {
cy.get('@selection')
.type(replaceMod(HOT_KEY_MAP['strikethrough']))
.confirmMarkdownEditorContent(
`
<p>
<s>foo</s>
</p>
`,
)
.type(replaceMod(HOT_KEY_MAP['strikethrough']));
});
});
describe('code', () => {
it('pressing mod+shift+c displays a code block around the text', () => {
cy.get('@selection')
.type(replaceMod(HOT_KEY_MAP['code']))
.confirmMarkdownEditorContent(
`
<p>
<code>foo</code>
</p>
`,
)
.type(replaceMod(HOT_KEY_MAP['code']));
});
});
describe('link', () => {
before(() => {});
it('pressing mod+k transforms the text to a link', () => {
cy.window().then(win => {
cy.get('@selection').type(replaceMod(HOT_KEY_MAP['link']));
cy.stub(win, 'prompt').returns('https://google.com');
cy.confirmMarkdownEditorContent('<p><a>foo</a></p>').type(
replaceMod(HOT_KEY_MAP['link']),
);
});
});
});
describe('headings', () => {
for (let i = 1; i <= 6; i++) {
it(`pressing mod+${i} transforms the text to a heading`, () => {
cy.get('@selection')
.type(replaceMod(HOT_KEY_MAP[`heading-${headingNumberToWord[i]}`]))
.confirmMarkdownEditorContent(`<h${i}>foo</h${i}>`)
.type(replaceMod(HOT_KEY_MAP[`heading-${headingNumberToWord[i]}`]));
});
}
});
});
});

View File

@ -0,0 +1,64 @@
describe('Markdown widget link', () => {
before(() => {
Cypress.config('defaultCommandTimeout', 4000);
cy.task('setupBackend', { backend: 'test' });
});
beforeEach(() => {
cy.loginAndNewPost();
cy.clearMarkdownEditorContent();
});
after(() => {
cy.task('teardownBackend', { backend: 'test' });
});
describe('link', () => {
it('can add a new valid link', () => {
const link = 'https://www.staticcms.org/';
cy.window().then(win => {
cy.stub(win, 'prompt').returns(link);
});
cy.focused().clickLinkButton();
cy.confirmMarkdownEditorContent(`<p><a>${link}</a></p>`);
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(300);
cy.clickModeToggle();
cy.confirmRawEditorContent(`<${link}>`);
});
it('can add a new invalid link', () => {
const link = 'www.staticcms.org';
cy.window().then(win => {
cy.stub(win, 'prompt').returns(link);
});
cy.focused().clickLinkButton();
cy.confirmMarkdownEditorContent(`<p><a>${link}</a></p>`);
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(300);
cy.clickModeToggle();
cy.confirmRawEditorContent(`[${link}](${link})`);
});
it('can select existing text as link', () => {
const link = 'https://www.staticcms.org';
cy.window().then(win => {
cy.stub(win, 'prompt').returns(link);
});
const text = 'Static CMS';
cy.focused().getMarkdownEditor().type(text).setSelection(text).clickLinkButton();
cy.confirmMarkdownEditorContent(`<p><a>${text}</a></p>`);
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(300);
cy.clickModeToggle();
cy.confirmRawEditorContent(`[${text}](${link})`);
});
});
});

View File

@ -0,0 +1,734 @@
describe('Markdown widget', () => {
describe('list', () => {
before(() => {
Cypress.config('defaultCommandTimeout', 4000);
cy.task('setupBackend', { backend: 'test' });
});
beforeEach(() => {
cy.loginAndNewPost();
cy.clearMarkdownEditorContent();
});
after(() => {
cy.task('teardownBackend', { backend: 'test' });
});
// describe('toolbar buttons', () => {
it('creates and focuses empty list', () => {
cy.clickUnorderedListButton().confirmMarkdownEditorContent(`
<ul>
<li>
<p></p>
</li>
</ul>
`);
});
it('removes list', () => {
cy.clickUnorderedListButton().clickUnorderedListButton().confirmMarkdownEditorContent(`
<p></p>
`);
});
it('converts a list item to a paragraph block which is a sibling of the parent list', () => {
cy.clickUnorderedListButton().type('foo').enter().clickUnorderedListButton()
.confirmMarkdownEditorContent(`
<ul>
<li>
<p>foo</p>
</li>
</ul>
<p></p>
`);
});
it('converts empty nested list item to empty paragraph block in parent list item', () => {
cy
.clickUnorderedListButton()
.type('foo')
.enter()
.tabkey()
.type('bar')
.enter()
.tabkey()
.confirmMarkdownEditorContent(
`
<ul>
<li>
<p>foo</p>
<ul>
<li>
<p>bar</p>
<ul>
<li>
<p></p>
</li>
</ul>
</li>
</ul>
</li>
</ul>
`,
)
.clickUnorderedListButton()
.confirmMarkdownEditorContent(
`
<ul>
<li>
<p>foo</p>
<ul>
<li>
<p>bar</p>
<p></p>
</li>
</ul>
</li>
</ul>
`,
)
.backspace({ times: 4 })
.clickUnorderedListButton().confirmMarkdownEditorContent(`
<ul>
<li>
<p>foo</p>
<p></p>
</li>
</ul>
`);
});
it('moves nested list item content to parent list item when in first block', () => {
cy
.clickUnorderedListButton()
.type('foo')
.enter()
.tabkey()
.type('bar')
.enter()
.tabkey()
.type('baz')
.clickUnorderedListButton()
.confirmMarkdownEditorContent(
`
<ul>
<li>
<p>foo</p>
<ul>
<li>
<p>bar</p>
<p>baz</p>
</li>
</ul>
</li>
</ul>
`,
)
.up()
.clickUnorderedListButton()
.confirmMarkdownEditorContent(
`
<ul>
<li>
<p>foo</p>
<p>bar</p>
<p>baz</p>
</li>
</ul>
`,
)
.up()
.clickUnorderedListButton().confirmMarkdownEditorContent(`
<p>foo</p>
<p>bar</p>
<p>baz</p>
`);
});
it('affects only the current block with collapsed selection', () => {
cy
.focused()
.type('foo')
.enter()
.type('bar')
.enter()
.type('baz')
.up()
.clickUnorderedListButton().confirmMarkdownEditorContent(`
<p>foo</p>
<ul>
<li>
<p>bar</p>
</li>
</ul>
<p>baz</p>
`);
});
it('wrap each bottom-most block in a selection with a list item block', () => {
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy
.focused()
.type('foo')
.enter()
.type('bar')
.enter()
.type('baz')
.setSelection('foo', 'baz')
.wait(500)
.clickUnorderedListButton().confirmMarkdownEditorContent(`
<ul>
<li>
<p>foo</p>
</li>
<li>
<p>bar</p>
</li>
<li>
<p>baz</p>
</li>
</ul>
`);
});
it('unwraps list item block from each selected list item and unwraps all of them from the outer list block', () => {
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy
.clickUnorderedListButton()
.type('foo')
.enter()
.type('bar')
.enter()
.type('baz')
.setSelection('foo', 'baz')
.wait(500)
.clickUnorderedListButton().confirmMarkdownEditorContent(`
<p>foo</p>
<p>bar</p>
<p>baz</p>
`);
});
it('combines adjacent same-typed lists, not differently typed lists', () => {
cy.focused()
.type('foo')
.enter()
.type('bar')
.enter()
.type('baz')
.up()
.clickUnorderedListButton()
.up()
.clickUnorderedListButton()
.confirmMarkdownEditorContent(
`
<ul>
<li>
<p>foo</p>
</li>
<li>
<p>bar</p>
</li>
</ul>
<p>baz</p>
`,
)
.down({ times: 2 })
.focused()
.clickUnorderedListButton()
.confirmMarkdownEditorContent(
`
<ul>
<li>
<p>foo</p>
</li>
<li>
<p>bar</p>
</li>
<li>
<p>baz</p>
</li>
</ul>
`,
)
.up()
.enter()
.type('qux')
.tabkey()
.confirmMarkdownEditorContent(
`
<ul>
<li>
<p>foo</p>
</li>
<li>
<p>bar</p>
<ul>
<li>
<p>qux</p>
</li>
</ul>
</li>
<li>
<p>baz</p>
</li>
</ul>
`,
)
.up()
.enter()
.type('quux')
.confirmMarkdownEditorContent(
`
<ul>
<li>
<p>foo</p>
</li>
<li>
<p>bar</p>
<ul>
<li>
<p>quux</p>
</li>
<li>
<p>qux</p>
</li>
</ul>
</li>
<li>
<p>baz</p>
</li>
</ul>
`,
)
.clickOrderedListButton()
.confirmMarkdownEditorContent(
`
<ul>
<li>
<p>foo</p>
</li>
<li>
<p>bar</p>
<ol>
<li>
<p>quux</p>
</li>
</ol>
<ul>
<li>
<p>qux</p>
</li>
</ul>
</li>
<li>
<p>baz</p>
</li>
</ul>
`,
)
.setSelection({
anchorQuery: 'ul > li > ol p',
anchorOffset: 1,
focusQuery: 'ul > li > ul:last-child p',
focusOffset: 2,
});
});
// while this works on dev environemnt, it will always fail in cypress - has something to do with text selection
// it('affects only selected list items', () => {
// cy
// .clickUnorderedListButton()
// .type('foo')
// .enter()
// .type('bar')
// .enter()
// .type('baz')
// .setSelection('bar')
// .clickUnorderedListButton()
// .confirmMarkdownEditorContent(
// `
// <ul>
// <li>
// <p>foo</p>
// </li>
// </ul>
// <p>bar</p>
// <ul>
// <li>
// <p>baz</p>
// </li>
// </ul>
// `,
// )
// .clickUnorderedListButton()
// .setSelection('bar', 'baz')
// .clickUnorderedListButton()
// .confirmMarkdownEditorContent(
// `
// <ul>
// <li>
// <p>foo</p>
// </li>
// </ul>
// <p>bar</p>
// <p>baz</p>
// `,
// )
// .clickUnorderedListButton()
// .confirmMarkdownEditorContent(
// `
// <ul>
// <li>
// <p>foo</p>
// </li>
// <li>
// <p>bar</p>
// </li>
// <li>
// <p>baz</p>
// </li>
// </ul>
// `,
// )
// .setSelection('baz')
// .clickUnorderedListButton()
// .confirmMarkdownEditorContent(
// `
// <ul>
// <li>
// <p>foo</p>
// </li>
// <li>
// <p>bar</p>
// </li>
// </ul>
// <p>baz</p>
// `,
// )
// .clickUnorderedListButton()
// .tabkey()
// .setCursorAfter('baz')
// .enter()
// .tabkey()
// .type('qux')
// .confirmMarkdownEditorContent(
// `
// <ul>
// <li>
// <p>foo</p>
// </li>
// <li>
// <p>bar</p>
// <ul>
// <li>
// <p>baz</p>
// <ul>
// <li>
// <p>qux</p>
// </li>
// </ul>
// </li>
// </ul>
// </li>
// </ul>
// `,
// )
// .setSelection('baz')
// .clickOrderedListButton()
// .confirmMarkdownEditorContent(
// `
// <ul>
// <li>
// <p>foo</p>
// </li>
// <li>
// <p>bar</p>
// <ol>
// <li>
// <p>baz</p>
// <ul>
// <li>
// <p>qux</p>
// </li>
// </ul>
// </li>
// </ol>
// </li>
// </ul>
// `,
// )
// .setCursorAfter('qux')
// .enter({ times: 2 })
// .clickUnorderedListButton()
// .confirmMarkdownEditorContent(`
// <ul>
// <li>
// <p>foo</p>
// </li>
// <li>
// <p>bar</p>
// <ol>
// <li>
// <p>baz</p>
// <ul>
// <li>
// <p>qux</p>
// </li>
// </ul>
// </li>
// </ol>
// <ul>
// <li>
// <p></p>
// </li>
// </ul>
// </li>
// </ul>
// `);
// });
// });
// });
// describe('on Enter', () => {
it('removes the list item and list if empty', () => {
cy.clickUnorderedListButton().enter().confirmMarkdownEditorContent(`
<p></p>
`);
});
it('creates a new list item in a non-empty list', () => {
cy
.clickUnorderedListButton()
.type('foo')
.enter()
.confirmMarkdownEditorContent(
`
<ul>
<li>
<p>foo</p>
</li>
<li>
<p></p>
</li>
</ul>
`,
)
.type('bar')
.enter().confirmMarkdownEditorContent(`
<ul>
<li>
<p>foo</p>
</li>
<li>
<p>bar</p>
</li>
<li>
<p></p>
</li>
</ul>
`);
});
it('creates a new default block below a list when hitting Enter twice on an empty list item of the list', () => {
cy.clickUnorderedListButton().type('foo').enter({ times: 2 }).confirmMarkdownEditorContent(`
<ul>
<li>
<p>foo</p>
</li>
</ul>
<p></p>
`);
});
// });
// describe('on Backspace', () => {
it('removes the list item and list if empty', () => {
cy.clickUnorderedListButton().backspace().confirmMarkdownEditorContent(`
<p></p>
`);
});
it('removes the list item if list not empty', () => {
cy.clickUnorderedListButton().type('foo').enter().backspace().confirmMarkdownEditorContent(`
<ul>
<li>
<p>foo</p>
<p></p>
</li>
</ul>
`);
});
it('does not remove list item if empty with non-default block', () => {
cy.clickUnorderedListButton().clickHeadingOneButton().backspace()
.confirmMarkdownEditorContent(`
<ul>
<li>
<p></p>
</li>
</ul>
`);
});
// });
// describe('on Tab', () => {
it('does nothing in top level list', () => {
cy
.clickUnorderedListButton()
.tabkey()
.confirmMarkdownEditorContent(
`
<ul>
<li>
<p></p>
</li>
</ul>
`,
)
.type('foo')
.tabkey().confirmMarkdownEditorContent(`
<ul>
<li>
<p>foo</p>
</li>
</ul>
`);
});
it('indents nested list items', () => {
cy
.clickUnorderedListButton()
.type('foo')
.enter()
.type('bar')
.tabkey()
.confirmMarkdownEditorContent(
`
<ul>
<li>
<p>foo</p>
<ul>
<li>
<p>bar</p>
</li>
</ul>
</li>
</ul>
`,
)
.enter()
.tabkey().confirmMarkdownEditorContent(`
<ul>
<li>
<p>foo</p>
<ul>
<li>
<p>bar</p>
<ul>
<li>
<p></p>
</li>
</ul>
</li>
</ul>
</li>
</ul>
`);
});
it('only nests up to one level down from the parent list', () => {
cy.clickUnorderedListButton().type('foo').enter().tabkey().confirmMarkdownEditorContent(`
<ul>
<li>
<p>foo</p>
<ul>
<li>
<p></p>
</li>
</ul>
</li>
</ul>
`);
});
it('unindents nested list items with shift', () => {
cy.clickUnorderedListButton().type('foo').enter().tabkey().tabkey({ shift: true })
.confirmMarkdownEditorContent(`
<ul>
<li>
<p>foo</p>
</li>
<li>
<p></p>
</li>
</ul>
`);
});
it('indents and unindents from one level below parent back to document root', () => {
cy
.clickUnorderedListButton()
.type('foo')
.enter()
.tabkey()
.type('bar')
.enter()
.tabkey()
.type('baz')
.confirmMarkdownEditorContent(
`
<ul>
<li>
<p>foo</p>
<ul>
<li>
<p>bar</p>
<ul>
<li>
<p>baz</p>
</li>
</ul>
</li>
</ul>
</li>
</ul>
`,
)
.tabkey({ shift: true })
.confirmMarkdownEditorContent(
`
<ul>
<li>
<p>foo</p>
<ul>
<li>
<p>bar</p>
</li>
<li>
<p>baz</p>
</li>
</ul>
</li>
</ul>
`,
)
.tabkey({ shift: true }).confirmMarkdownEditorContent(`
<ul>
<li>
<p>foo</p>
<ul>
<li>
<p>bar</p>
</li>
</ul>
</li>
<li>
<p>baz</p>
</li>
</ul>
`);
});
// });
});
});

View File

@ -0,0 +1,31 @@
describe('Markdown widget', () => {
describe('code mark', () => {
before(() => {
Cypress.config('defaultCommandTimeout', 4000);
cy.task('setupBackend', { backend: 'test' });
});
beforeEach(() => {
cy.loginAndNewPost();
cy.clearMarkdownEditorContent();
});
after(() => {
cy.task('teardownBackend', { backend: 'test' });
});
describe('toolbar button', () => {
it('can combine code mark with other marks', () => {
cy.clickItalicButton().type('foo').setSelection('oo').clickCodeButton()
.confirmMarkdownEditorContent(`
<p>
<em>f</em>
<code>
<em>oo</em>
</code>
</p>
`);
});
});
});
});

View File

@ -0,0 +1,370 @@
describe('Markdown widget', () => {
describe('quote block', () => {
before(() => {
Cypress.config('defaultCommandTimeout', 4000);
cy.task('setupBackend', { backend: 'test' });
});
beforeEach(() => {
cy.loginAndNewPost();
cy.clearMarkdownEditorContent();
});
after(() => {
cy.task('teardownBackend', { backend: 'test' });
});
// describe('toggle quote', () => {
it('toggles empty quote block on and off in empty editor', () => {
cy
.clickQuoteButton()
.confirmMarkdownEditorContent(
`
<blockquote>
<p></p>
</blockquote>
`,
)
.clickQuoteButton().confirmMarkdownEditorContent(`
<p></p>
`);
});
it('toggles empty quote block on and off for current block', () => {
cy
.focused()
.type('foo')
.clickQuoteButton()
.confirmMarkdownEditorContent(
`
<blockquote>
<p>foo</p>
</blockquote>
`,
)
.clickQuoteButton().confirmMarkdownEditorContent(`
<p>foo</p>
`);
});
it('toggles entire quote block without expanded selection', () => {
cy.clickQuoteButton().type('foo').enter().type('bar').clickQuoteButton()
.confirmMarkdownEditorContent(`
<p>foo</p>
<p>bar</p>
`);
});
it('toggles entire quote block with complex content', () => {
cy
.clickQuoteButton()
.clickUnorderedListButton()
.clickHeadingOneButton()
.type('foo')
.enter({ times: 2 }) // First Enter creates new list item. Second Enter turns that list item into a default block.
.clickQuoteButton() // Unwrap the quote block.
.confirmMarkdownEditorContent(`
<ul>
<li>
<h1>foo</h1>
</li>
</ul>
<p></p>
`);
});
it('toggles empty quote block on and off for selected blocks', () => {
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy
.focused()
.type('foo')
.enter()
.type('bar')
.setSelection('foo', 'bar')
.wait(500)
.clickQuoteButton()
.confirmMarkdownEditorContent(
`
<blockquote>
<p>foo</p>
<p>bar</p>
</blockquote>
`,
)
.clickQuoteButton()
.confirmMarkdownEditorContent(
`
<p>foo</p>
<p>bar</p>
`,
)
.clickQuoteButton().confirmMarkdownEditorContent(`
<blockquote>
<p>foo</p>
<p>bar</p>
</blockquote>
`);
});
it('toggles empty quote block on and off for partially selected blocks', () => {
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy
.focused()
.type('foo')
.enter()
.type('bar')
.setSelection('oo', 'ba')
.wait(500)
.clickQuoteButton()
.confirmMarkdownEditorContent(
`
<blockquote>
<p>foo</p>
<p>bar</p>
</blockquote>
`,
)
.clickQuoteButton()
.confirmMarkdownEditorContent(
`
<p>foo</p>
<p>bar</p>
`,
)
.clickQuoteButton().confirmMarkdownEditorContent(`
<blockquote>
<p>foo</p>
<p>bar</p>
</blockquote>
`);
});
it('toggles quote block on and off for multiple selected list items', () => {
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy
.focused()
.clickUnorderedListButton()
.type('foo')
.enter()
.type('bar')
.setSelection('foo', 'bar')
.wait(500)
.clickQuoteButton()
.confirmMarkdownEditorContent(
`
<blockquote>
<ul>
<li>
<p>foo</p>
</li>
<li>
<p>bar</p>
</li>
</ul>
</blockquote>
`,
)
.clickQuoteButton()
.confirmMarkdownEditorContent(
`
<ul>
<li>
<p>foo</p>
</li>
<li>
<p>bar</p>
</li>
</ul>
`,
)
.setCursorAfter('bar')
.wait(500)
.enter()
.type('baz')
.setSelection('bar', 'baz')
.wait(500)
.clickQuoteButton().confirmMarkdownEditorContent(`
<ul>
<li>
<p>foo</p>
</li>
</ul>
<blockquote>
<ul>
<li>
<p>bar</p>
</li>
<li>
<p>baz</p>
</li>
</ul>
</blockquote>
`);
});
it('creates new quote block if parent is not a quote, can deeply nest', () => {
cy.clickQuoteButton()
.clickUnorderedListButton()
.clickQuoteButton()
.clickUnorderedListButton()
.clickQuoteButton()
.clickUnorderedListButton()
.clickQuoteButton()
.type('foo')
// Content should contains 4 <blockquote> tags and 3 <ul> tags
.confirmMarkdownEditorContent(
`
<blockquote>
<ul>
<li>
<blockquote>
<ul>
<li>
<blockquote>
<ul>
<li>
<blockquote>
<p>foo</p>
</blockquote>
</li>
</ul>
</blockquote>
</li>
</ul>
</blockquote>
</li>
</ul>
</blockquote>
`,
)
/*
* First Enter creates new paragraph within the innermost block quote.
* Second Enter moves that paragraph one level up to become sibling of the previous quote block and direct child of a list item.
* Third Enter to turn that paragraph into a list item and move it one level up.
* Repeat the circle for three more times to reach the second list item of the outermost list block.
* Then Enter again to turn that list item into a paragraph and move it one level up to become sibling of the outermost list and
* direct child of the outermost block quote.
*/
.enter({ times: 10 })
.type('bar')
.confirmMarkdownEditorContent(
`
<blockquote>
<ul>
<li>
<blockquote>
<ul>
<li>
<blockquote>
<ul>
<li>
<blockquote>
<p>foo</p>
</blockquote>
</li>
</ul>
</blockquote>
</li>
</ul>
</blockquote>
</li>
</ul>
<p>bar</p>
</blockquote>
`,
)
/* The GOAL is to delete all the text content inside this deeply nested block quote and turn it into a default paragraph block on top level.
* We need:
* 3 Backspace to delete the word “bar”.
* 1 Backspace to remove the paragraph that contains bar and bring cursor to the end of the unordered list which is direct child of the outermost block quote.
* 3 Backspace to remove the word “foo”.
* 1 Backspace to remove the current block quote that the cursor is on, 1 Backspace to remove the list that wraps the block quote. Repeat this step for three times for a total of 6 Backspace until the cursor is on the outermost block quote.
* 1 Backspace to remove to toggle off the outermost block quote and turn it into a default paragraph.
* Total Backspaces required: 3 + 1 + 3 + ((1 + 1) * 3) + 1 = 14
*/
.backspace({ times: 14 });
});
// });
// describe('backspace inside quote', () => {
it('joins two paragraphs', () => {
cy.clickQuoteButton().type('foo').enter().type('bar').setCursorBefore('bar').backspace()
.confirmMarkdownEditorContent(`
<blockquote>
<p>foobar</p>
</blockquote>
`);
});
it('joins quote with previous quote', () => {
cy
.clickQuoteButton()
.type('foo')
.enter({ times: 2 })
.clickQuoteButton()
.type('bar')
.confirmMarkdownEditorContent(
`
<blockquote>
<p>foo</p>
</blockquote>
<blockquote>
<p>bar</p>
</blockquote>
`,
)
.setCursorBefore('bar')
.backspace().confirmMarkdownEditorContent(`
<blockquote>
<p>foo</p>
<p>bar</p>
</blockquote>
`);
});
it('removes first block from quote when focused at first block at start', () => {
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy
.clickQuoteButton()
.type('foo')
.enter()
.type('bar')
.setCursorBefore('foo')
.wait(500)
.backspace().confirmMarkdownEditorContent(`
<p>foo</p>
<blockquote>
<p>bar</p>
</blockquote>
`);
});
// });
// describe('enter inside quote', () => {
it('creates new block inside quote', () => {
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy
.clickQuoteButton()
.type('foo')
.enter()
.confirmMarkdownEditorContent(
`
<blockquote>
<p>foo</p>
<p></p>
</blockquote>
`,
)
.type('bar')
.setCursorAfter('ba')
.wait(500)
.enter().confirmMarkdownEditorContent(`
<blockquote>
<p>foo</p>
<p>ba</p>
<p>r</p>
</blockquote>
`);
});
it('creates new block after quote from empty last block', () => {
cy.clickQuoteButton().type('foo').enter().enter().confirmMarkdownEditorContent(`
<blockquote>
<p>foo</p>
</blockquote>
<p></p>
`);
});
// });
});
});

View File

@ -0,0 +1,27 @@
import fixture from '../common/media_library';
import { entry1 } from '../common/entries';
import * as specUtils from '../common/spec_utils';
const backend = 'bitbucket';
describe('BitBucket Backend Media Library - REST API', () => {
let taskResult = { data: {} };
before(() => {
specUtils.before(taskResult, {}, backend);
});
after(() => {
specUtils.after(taskResult, backend);
});
beforeEach(() => {
specUtils.beforeEach(taskResult, backend);
});
afterEach(() => {
specUtils.afterEach(taskResult, backend);
});
fixture({ entries: [entry1], getUser: () => taskResult.data.user });
});

View File

@ -0,0 +1,28 @@
import fixture from '../common/media_library';
import { entry1 } from '../common/entries';
import * as specUtils from '../common/spec_utils';
const backend = 'bitbucket';
const lfs = true;
describe('BitBucket Backend Media Library - Large Media', () => {
let taskResult = { data: {} };
before(() => {
specUtils.before(taskResult, { lfs }, backend);
});
after(() => {
specUtils.after(taskResult, backend);
});
beforeEach(() => {
specUtils.beforeEach(taskResult, backend);
});
afterEach(() => {
specUtils.afterEach(taskResult, backend);
});
fixture({ entries: [entry1], getUser: () => taskResult.data.user });
});

View File

@ -0,0 +1,28 @@
import fixture from '../common/media_library';
import { entry1 } from '../common/entries';
import * as specUtils from '../common/spec_utils';
const backend = 'git-gateway';
const provider = 'github';
describe('Git Gateway (GitHub) Backend Media Library - Large Media', () => {
let taskResult = { data: {} };
before(() => {
specUtils.before(taskResult, { publish_mode: 'editorial_workflow', provider }, backend);
});
after(() => {
specUtils.after(taskResult, backend);
});
beforeEach(() => {
specUtils.beforeEach(taskResult, backend);
});
afterEach(() => {
specUtils.afterEach(taskResult, backend);
});
fixture({ entries: [entry1], getUser: () => taskResult.data.user });
});

View File

@ -0,0 +1,28 @@
import fixture from '../common/media_library';
import { entry1 } from '../common/entries';
import * as specUtils from '../common/spec_utils';
const backend = 'git-gateway';
const provider = 'gitlab';
describe('Git Gateway (GitLab) Backend Media Library - Large Media', () => {
let taskResult = { data: {} };
before(() => {
specUtils.before(taskResult, { publish_mode: 'editorial_workflow', provider }, backend);
});
after(() => {
specUtils.after(taskResult, backend);
});
beforeEach(() => {
specUtils.beforeEach(taskResult, backend);
});
afterEach(() => {
specUtils.afterEach(taskResult, backend);
});
fixture({ entries: [entry1], getUser: () => taskResult.data.user });
});

View File

@ -0,0 +1,34 @@
import fixture from '../common/media_library';
import { entry1 } from '../common/entries';
import * as specUtils from '../common/spec_utils';
const backend = 'github';
describe('GitHub Backend Media Library - GraphQL API', () => {
const taskResult = { data: {} };
before(() => {
specUtils.before(
taskResult,
{
backend: { use_graphql: true },
publish_mode: 'editorial_workflow',
},
backend,
);
});
after(() => {
specUtils.after(taskResult, backend);
});
beforeEach(() => {
specUtils.beforeEach(taskResult, backend);
});
afterEach(() => {
specUtils.afterEach(taskResult, backend);
});
fixture({ entries: [entry1], getUser: () => taskResult.data.user });
});

View File

@ -0,0 +1,34 @@
import fixture from '../common/media_library';
import { entry1 } from '../common/entries';
import * as specUtils from '../common/spec_utils';
const backend = 'github';
describe('GitHub Backend Media Library - REST API', () => {
let taskResult = { data: {} };
before(() => {
specUtils.before(
taskResult,
{
backend: { use_graphql: false },
publish_mode: 'editorial_workflow',
},
backend,
);
});
after(() => {
specUtils.after(taskResult, backend);
});
beforeEach(() => {
specUtils.beforeEach(taskResult, backend);
});
afterEach(() => {
specUtils.afterEach(taskResult, backend);
});
fixture({ entries: [entry1], getUser: () => taskResult.data.user });
});

View File

@ -0,0 +1,27 @@
import fixture from '../common/media_library';
import { entry1 } from '../common/entries';
import * as specUtils from '../common/spec_utils';
const backend = 'gitlab';
describe('GitLab Backend Media Library - REST API', () => {
let taskResult = { data: {} };
before(() => {
specUtils.before(taskResult, { publish_mode: 'editorial_workflow' }, backend);
});
after(() => {
specUtils.after(taskResult, backend);
});
beforeEach(() => {
specUtils.beforeEach(taskResult, backend);
});
afterEach(() => {
specUtils.afterEach(taskResult, backend);
});
fixture({ entries: [entry1], getUser: () => taskResult.data.user });
});

View File

@ -0,0 +1,29 @@
import fixture from '../common/media_library';
import * as specUtils from '../common/spec_utils';
import { entry1 } from '../common/entries';
const backend = 'proxy';
const mode = 'git';
describe(`Proxy Backend Media Library - '${mode}' mode`, () => {
let taskResult = { data: {} };
before(() => {
specUtils.before(taskResult, { publish_mode: 'editorial_workflow', mode }, backend);
Cypress.config('defaultCommandTimeout', 5 * 1000);
});
after(() => {
specUtils.after(taskResult, backend);
});
beforeEach(() => {
specUtils.beforeEach(taskResult, backend);
});
afterEach(() => {
specUtils.afterEach(taskResult, backend);
});
fixture({ entries: [entry1], getUser: () => taskResult.data.user });
});

View File

@ -0,0 +1,21 @@
import fixture from '../common/media_library';
const entries = [
{
Title: 'first title',
Body: 'first body',
},
];
describe('Test Backend Media Library', () => {
after(() => {
cy.task('teardownBackend', { backend: 'test' });
});
before(() => {
Cypress.config('defaultCommandTimeout', 4000);
cy.task('setupBackend', { backend: 'test' });
});
fixture({ entries });
});

View File

@ -0,0 +1,71 @@
import { login } from '../../utils/steps';
const search = (term, collection) => {
cy.get('[class*=SearchInput]').clear({ force: true });
cy.get('[class*=SearchInput]').type(term, { force: true });
cy.get('[class*=SuggestionsContainer]').within(() => {
cy.contains(collection).click();
});
};
const assertSearchHeading = title => {
cy.get('[class*=SearchResultHeading]').should('have.text', title);
};
const assertSearchResult = (text, collection) => {
cy.get('[class*=ListCardLink] h2').contains(collection ?? text);
};
const assertNotInSearch = text => {
cy.get('[class*=ListCardLink] h2').contains(text).should('not.exist');
};
describe('Search Suggestion', () => {
before(() => {
Cypress.config('defaultCommandTimeout', 4000);
cy.task('setupBackend', { backend: 'test' });
});
after(() => {
cy.task('teardownBackend', { backend: 'test' });
});
beforeEach(() => {
login();
});
it('can search in all collections', () => {
search('this', 'All Collections');
assertSearchHeading('Search Results for "this"');
assertSearchResult('This is post # 20', 'Posts');
assertSearchResult('This is a TOML front matter post', 'Posts');
assertSearchResult('This is a JSON front matter post', 'Posts');
assertSearchResult('This is a YAML front matter post', 'Posts');
assertSearchResult('This FAQ item # 5', 'FAQ');
});
it('can search in posts collection', () => {
search('this', 'Posts');
assertSearchHeading('Search Results for "this" in Posts');
assertSearchResult('This is post # 20');
assertSearchResult('This is a TOML front matter post');
assertSearchResult('This is a JSON front matter post');
assertSearchResult('This is a YAML front matter post');
assertNotInSearch('This FAQ item # 5');
});
it('can search in faq collection', () => {
search('this', 'FAQ');
assertSearchHeading('Search Results for "this" in FAQ');
assertSearchResult('This FAQ item # 5');
assertNotInSearch('This is post # 20');
});
});

View File

@ -0,0 +1,30 @@
import fixture from '../common/simple_workflow';
import * as specUtils from '../common/spec_utils';
import type { TaskResult } from '../../interface';
const backend = 'bitbucket';
describe('BitBucket Backend Simple Workflow', () => {
let taskResult: TaskResult = { data: {} };
before(() => {
specUtils.before(taskResult, { publish_mode: 'simple' }, backend);
});
after(() => {
specUtils.after(backend);
});
beforeEach(() => {
specUtils.beforeEach(backend);
});
afterEach(() => {
specUtils.afterEach(backend);
});
fixture({
getUser: () => taskResult.data?.user,
});
});

View File

@ -0,0 +1,31 @@
import fixture from '../common/simple_workflow';
import * as specUtils from '../common/spec_utils';
import { entry1, entry2, entry3 } from '../common/entries';
const backend = 'git-gateway';
const provider = 'github';
describe('Git Gateway (GitHub) Backend Simple Workflow', () => {
let taskResult = { data: {} };
before(() => {
specUtils.before(taskResult, { publish_mode: 'simple', provider }, backend);
});
after(() => {
specUtils.after(taskResult, backend);
});
beforeEach(() => {
specUtils.beforeEach(taskResult, backend);
});
afterEach(() => {
specUtils.afterEach(taskResult, backend);
});
fixture({
entries: [entry1, entry2, entry3],
getUser: () => taskResult.data.user,
});
});

View File

@ -0,0 +1,31 @@
import fixture from '../common/simple_workflow';
import * as specUtils from '../common/spec_utils';
import { entry1, entry2, entry3 } from '../common/entries';
const backend = 'git-gateway';
const provider = 'gitlab';
describe('Git Gateway (GitLab) Backend Simple Workflow', () => {
let taskResult = { data: {} };
before(() => {
specUtils.before(taskResult, { publish_mode: 'simple', provider }, backend);
});
after(() => {
specUtils.after(taskResult, backend);
});
beforeEach(() => {
specUtils.beforeEach(taskResult, backend);
});
afterEach(() => {
specUtils.afterEach(taskResult, backend);
});
fixture({
entries: [entry1, entry2, entry3],
getUser: () => taskResult.data.user,
});
});

View File

@ -0,0 +1,37 @@
import fixture from '../common/simple_workflow';
import * as specUtils from '../common/spec_utils';
import { entry1, entry2, entry3 } from '../common/entries';
const backend = 'github';
describe('GitHub Backend Simple Workflow - GraphQL API', () => {
const taskResult = { data: {} };
before(() => {
specUtils.before(
taskResult,
{
backend: { use_graphql: true },
publish_mode: 'simple',
},
backend,
);
});
after(() => {
specUtils.after(taskResult, backend);
});
beforeEach(() => {
specUtils.beforeEach(taskResult, backend);
});
afterEach(() => {
specUtils.afterEach(taskResult, backend);
});
fixture({
entries: [entry1, entry2, entry3],
getUser: () => taskResult.data.user,
});
});

View File

@ -0,0 +1,37 @@
import fixture from '../common/simple_workflow';
import * as specUtils from '../common/spec_utils';
import { entry1, entry2, entry3 } from '../common/entries';
const backend = 'github';
describe('GitHub Backend Simple Workflow - REST API', () => {
let taskResult = { data: {} };
before(() => {
specUtils.before(
taskResult,
{
backend: { use_graphql: false },
publish_mode: 'simple',
},
backend,
);
});
after(() => {
specUtils.after(taskResult, backend);
});
beforeEach(() => {
specUtils.beforeEach(taskResult, backend);
});
afterEach(() => {
specUtils.afterEach(taskResult, backend);
});
fixture({
entries: [entry1, entry2, entry3],
getUser: () => taskResult.data.user,
});
});

View File

@ -0,0 +1,30 @@
import fixture from '../common/simple_workflow';
import * as specUtils from '../common/spec_utils';
import { entry1, entry2, entry3 } from '../common/entries';
const backend = 'gitlab';
describe('GitLab Backend Simple Workflow', () => {
let taskResult = { data: {} };
before(() => {
specUtils.before(taskResult, { publish_mode: 'simple' }, backend);
});
after(() => {
specUtils.after(taskResult, backend);
});
beforeEach(() => {
specUtils.beforeEach(taskResult, backend);
});
afterEach(() => {
specUtils.afterEach(taskResult, backend);
});
fixture({
entries: [entry1, entry2, entry3],
getUser: () => taskResult.data.user,
});
});

View File

@ -0,0 +1,32 @@
import fixture from '../common/simple_workflow';
import * as specUtils from '../common/spec_utils';
import { entry1, entry2, entry3 } from '../common/entries';
const backend = 'proxy';
const mode = 'fs';
describe(`Proxy Backend Simple Workflow - '${mode}' mode`, () => {
const taskResult = { data: {} };
before(() => {
specUtils.before(taskResult, { publish_mode: 'simple', mode }, backend);
Cypress.config('defaultCommandTimeout', 5 * 1000);
});
after(() => {
specUtils.after(taskResult, backend);
});
beforeEach(() => {
specUtils.beforeEach(taskResult, backend);
});
afterEach(() => {
specUtils.afterEach(taskResult, backend);
});
fixture({
entries: [entry1, entry2, entry3],
getUser: () => taskResult.data.user,
});
});

View File

@ -0,0 +1,35 @@
import fixture from '../common/simple_workflow';
import * as specUtils from '../common/spec_utils';
import { entry1, entry2, entry3 } from '../common/entries';
const backend = 'proxy';
const mode = 'git';
describe(`Proxy Backend Simple Workflow - '${mode}' mode`, () => {
let taskResult = { data: {} };
before(() => {
specUtils.before(taskResult, { publish_mode: 'simple', mode }, backend);
Cypress.config('defaultCommandTimeout', 5 * 1000);
});
after(() => {
specUtils.after(taskResult, backend);
});
beforeEach(() => {
if (Cypress.mocha.getRunner().suite.ctx.currentTest.title === 'can create an entry') {
Cypress.mocha.getRunner().suite.ctx.currentTest.skip();
}
specUtils.beforeEach(taskResult, backend);
});
afterEach(() => {
specUtils.afterEach(taskResult, backend);
});
fixture({
entries: [entry1, entry2, entry3],
getUser: () => taskResult.data.user,
});
});