Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-08-27 00:11:25 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-08-27 00:11:25 +0300
commit9f6c0ac9fd6921bc0b5190ed4d4eaf0ab1e1f2d7 (patch)
tree92f397ea19f1fec56491c99ce3b7862bb86fe8ce /spec/frontend
parenta56971e97f0385640c2f3568017bd221897b78ef (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend')
-rw-r--r--spec/frontend/content_editor/extensions/attachment_spec.js14
-rw-r--r--spec/frontend/content_editor/extensions/blockquote_spec.js19
-rw-r--r--spec/frontend/content_editor/extensions/code_block_highlight_spec.js15
-rw-r--r--spec/frontend/content_editor/services/markdown_serializer_spec.js360
-rw-r--r--spec/frontend/content_editor/services/markdown_sourcemap_spec.js17
-rw-r--r--spec/frontend/environments/edit_environment_spec.js52
-rw-r--r--spec/frontend/environments/environment_form_spec.js48
-rw-r--r--spec/frontend/fixtures/api_markdown.yml10
-rw-r--r--spec/frontend/lib/utils/dom_utils_spec.js15
9 files changed, 513 insertions, 37 deletions
diff --git a/spec/frontend/content_editor/extensions/attachment_spec.js b/spec/frontend/content_editor/extensions/attachment_spec.js
index 97a33b28cdd..9e7c31cca72 100644
--- a/spec/frontend/content_editor/extensions/attachment_spec.js
+++ b/spec/frontend/content_editor/extensions/attachment_spec.js
@@ -7,9 +7,17 @@ import Image from '~/content_editor/extensions/image';
import Link from '~/content_editor/extensions/link';
import Loading from '~/content_editor/extensions/loading';
import httpStatus from '~/lib/utils/http_status';
-import { loadMarkdownApiResult } from '../markdown_processing_examples';
import { createTestEditor, createDocBuilder } from '../test_utils';
+const PROJECT_WIKI_ATTACHMENT_IMAGE_HTML = `<p data-sourcepos="1:1-1:27" dir="auto">
+ <a class="no-attachment-icon" href="/group1/project1/-/wikis/test-file.png" target="_blank" rel="noopener noreferrer" data-canonical-src="test-file.png">
+ <img alt="test-file" class="lazy" data-src="/group1/project1/-/wikis/test-file.png" data-canonical-src="test-file.png">
+ </a>
+</p>`;
+const PROJECT_WIKI_ATTACHMENT_LINK_HTML = `<p data-sourcepos="1:1-1:26" dir="auto">
+ <a href="/group1/project1/-/wikis/test-file.zip" data-canonical-src="test-file.zip">test-file</a>
+</p>`;
+
describe('content_editor/extensions/attachment', () => {
let tiptapEditor;
let eq;
@@ -76,7 +84,7 @@ describe('content_editor/extensions/attachment', () => {
const base64EncodedFile = 'data:image/png;base64,Zm9v';
beforeEach(() => {
- renderMarkdown.mockResolvedValue(loadMarkdownApiResult('project_wiki_attachment_image'));
+ renderMarkdown.mockResolvedValue(PROJECT_WIKI_ATTACHMENT_IMAGE_HTML);
});
describe('when uploading succeeds', () => {
@@ -151,7 +159,7 @@ describe('content_editor/extensions/attachment', () => {
});
describe('when the file has a zip (or any other attachment) mime type', () => {
- const markdownApiResult = loadMarkdownApiResult('project_wiki_attachment_link');
+ const markdownApiResult = PROJECT_WIKI_ATTACHMENT_LINK_HTML;
beforeEach(() => {
renderMarkdown.mockResolvedValue(markdownApiResult);
diff --git a/spec/frontend/content_editor/extensions/blockquote_spec.js b/spec/frontend/content_editor/extensions/blockquote_spec.js
new file mode 100644
index 00000000000..c5b5044352d
--- /dev/null
+++ b/spec/frontend/content_editor/extensions/blockquote_spec.js
@@ -0,0 +1,19 @@
+import { multilineInputRegex } from '~/content_editor/extensions/blockquote';
+
+describe('content_editor/extensions/blockquote', () => {
+ describe.each`
+ input | matches
+ ${'>>> '} | ${true}
+ ${' >>> '} | ${true}
+ ${'\t>>> '} | ${true}
+ ${'>> '} | ${false}
+ ${'>>>x '} | ${false}
+ ${'> '} | ${false}
+ `('multilineInputRegex', ({ input, matches }) => {
+ it(`${matches ? 'matches' : 'does not match'}: "${input}"`, () => {
+ const match = new RegExp(multilineInputRegex).test(input);
+
+ expect(match).toBe(matches);
+ });
+ });
+});
diff --git a/spec/frontend/content_editor/extensions/code_block_highlight_spec.js b/spec/frontend/content_editor/extensions/code_block_highlight_spec.js
index 828fdb224fc..6a0a0c76825 100644
--- a/spec/frontend/content_editor/extensions/code_block_highlight_spec.js
+++ b/spec/frontend/content_editor/extensions/code_block_highlight_spec.js
@@ -1,9 +1,15 @@
import CodeBlockHighlight from '~/content_editor/extensions/code_block_highlight';
-import { loadMarkdownApiResult } from '../markdown_processing_examples';
import { createTestEditor } from '../test_utils';
+const CODE_BLOCK_HTML = `<pre class="code highlight js-syntax-highlight language-javascript" lang="javascript" v-pre="true">
+ <code>
+ <span id="LC1" class="line" lang="javascript">
+ <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">hello world</span><span class="dl">'</span><span class="p">)</span>
+ </span>
+ </code>
+</pre>`;
+
describe('content_editor/extensions/code_block_highlight', () => {
- let codeBlockHtmlFixture;
let parsedCodeBlockHtmlFixture;
let tiptapEditor;
@@ -12,10 +18,9 @@ describe('content_editor/extensions/code_block_highlight', () => {
beforeEach(() => {
tiptapEditor = createTestEditor({ extensions: [CodeBlockHighlight] });
- codeBlockHtmlFixture = loadMarkdownApiResult('code_block');
- parsedCodeBlockHtmlFixture = parseHTML(codeBlockHtmlFixture);
+ parsedCodeBlockHtmlFixture = parseHTML(CODE_BLOCK_HTML);
- tiptapEditor.commands.setContent(codeBlockHtmlFixture);
+ tiptapEditor.commands.setContent(CODE_BLOCK_HTML);
});
it('extracts language and params attributes from Markdown API output', () => {
diff --git a/spec/frontend/content_editor/services/markdown_serializer_spec.js b/spec/frontend/content_editor/services/markdown_serializer_spec.js
index 868473faa14..cd4560677f8 100644
--- a/spec/frontend/content_editor/services/markdown_serializer_spec.js
+++ b/spec/frontend/content_editor/services/markdown_serializer_spec.js
@@ -8,6 +8,7 @@ import HardBreak from '~/content_editor/extensions/hard_break';
import Heading from '~/content_editor/extensions/heading';
import HorizontalRule from '~/content_editor/extensions/horizontal_rule';
import Image from '~/content_editor/extensions/image';
+import InlineDiff from '~/content_editor/extensions/inline_diff';
import Italic from '~/content_editor/extensions/italic';
import Link from '~/content_editor/extensions/link';
import ListItem from '~/content_editor/extensions/list_item';
@@ -18,6 +19,8 @@ import Table from '~/content_editor/extensions/table';
import TableCell from '~/content_editor/extensions/table_cell';
import TableHeader from '~/content_editor/extensions/table_header';
import TableRow from '~/content_editor/extensions/table_row';
+import TaskItem from '~/content_editor/extensions/task_item';
+import TaskList from '~/content_editor/extensions/task_list';
import Text from '~/content_editor/extensions/text';
import markdownSerializer from '~/content_editor/services/markdown_serializer';
import { createTestEditor, createDocBuilder } from '../test_utils';
@@ -40,6 +43,7 @@ const tiptapEditor = createTestEditor({
Heading,
HorizontalRule,
Image,
+ InlineDiff,
Italic,
Link,
ListItem,
@@ -50,6 +54,8 @@ const tiptapEditor = createTestEditor({
TableCell,
TableHeader,
TableRow,
+ TaskItem,
+ TaskList,
Text,
],
});
@@ -67,6 +73,7 @@ const {
hardBreak,
horizontalRule,
image,
+ inlineDiff,
italic,
link,
listItem,
@@ -77,6 +84,8 @@ const {
tableCell,
tableHeader,
tableRow,
+ taskItem,
+ taskList,
},
} = createDocBuilder({
tiptapEditor,
@@ -91,6 +100,7 @@ const {
heading: { nodeType: Heading.name },
horizontalRule: { nodeType: HorizontalRule.name },
image: { nodeType: Image.name },
+ inlineDiff: { markType: InlineDiff.name },
italic: { nodeType: Italic.name },
link: { markType: Link.name },
listItem: { nodeType: ListItem.name },
@@ -101,6 +111,8 @@ const {
tableCell: { nodeType: TableCell.name },
tableHeader: { nodeType: TableHeader.name },
tableRow: { nodeType: TableRow.name },
+ taskItem: { nodeType: TaskItem.name },
+ taskList: { nodeType: TaskList.name },
},
});
@@ -111,6 +123,25 @@ const serialize = (...content) =>
});
describe('markdownSerializer', () => {
+ it('correctly serializes bold', () => {
+ expect(serialize(paragraph(bold('bold')))).toBe('**bold**');
+ });
+
+ it('correctly serializes italics', () => {
+ expect(serialize(paragraph(italic('italics')))).toBe('_italics_');
+ });
+
+ it('correctly serializes inline diff', () => {
+ expect(
+ serialize(
+ paragraph(
+ inlineDiff({ type: 'addition' }, '+30 lines'),
+ inlineDiff({ type: 'deletion' }, '-10 lines'),
+ ),
+ ),
+ ).toBe('{++30 lines+}{--10 lines-}');
+ });
+
it('correctly serializes a line break', () => {
expect(serialize(paragraph('hello', hardBreak(), 'world'))).toBe('hello\\\nworld');
});
@@ -121,6 +152,12 @@ describe('markdownSerializer', () => {
);
});
+ it('correctly serializes a plain URL link', () => {
+ expect(serialize(paragraph(link({ href: 'https://example.com' }, 'https://example.com')))).toBe(
+ '<https://example.com>',
+ );
+ });
+
it('correctly serializes a link with a title', () => {
expect(
serialize(
@@ -129,6 +166,16 @@ describe('markdownSerializer', () => {
).toBe('[example url](https://example.com "click this link")');
});
+ it('correctly serializes a plain URL link with a title', () => {
+ expect(
+ serialize(
+ paragraph(
+ link({ href: 'https://example.com', title: 'link title' }, 'https://example.com'),
+ ),
+ ),
+ ).toBe('[https://example.com](https://example.com "link title")');
+ });
+
it('correctly serializes a link with a canonicalSrc', () => {
expect(
serialize(
@@ -146,6 +193,115 @@ describe('markdownSerializer', () => {
).toBe('[download file](file.zip "click here to download")');
});
+ it('correctly serializes strikethrough', () => {
+ expect(serialize(paragraph(strike('deleted content')))).toBe('~~deleted content~~');
+ });
+
+ it('correctly serializes blockquotes with hard breaks', () => {
+ expect(serialize(blockquote('some text', hardBreak(), hardBreak(), 'new line'))).toBe(
+ `
+> some text\\
+> \\
+> new line
+ `.trim(),
+ );
+ });
+
+ it('correctly serializes blockquote with multiple block nodes', () => {
+ expect(serialize(blockquote(paragraph('some paragraph'), codeBlock('var x = 10;')))).toBe(
+ `
+> some paragraph
+>
+> \`\`\`
+> var x = 10;
+> \`\`\`
+ `.trim(),
+ );
+ });
+
+ it('correctly serializes a multiline blockquote', () => {
+ expect(
+ serialize(
+ blockquote(
+ { multiline: true },
+ paragraph('some paragraph with ', bold('bold')),
+ codeBlock('var y = 10;'),
+ ),
+ ),
+ ).toBe(
+ `
+>>>
+some paragraph with **bold**
+
+\`\`\`
+var y = 10;
+\`\`\`
+
+>>>
+ `.trim(),
+ );
+ });
+
+ it('correctly serializes a code block with language', () => {
+ expect(
+ serialize(
+ codeBlock(
+ { language: 'json' },
+ 'this is not really json but just trying out whether this case works or not',
+ ),
+ ),
+ ).toBe(
+ `
+\`\`\`json
+this is not really json but just trying out whether this case works or not
+\`\`\`
+ `.trim(),
+ );
+ });
+
+ it('correctly serializes emoji', () => {
+ expect(serialize(paragraph(emoji({ name: 'dog' })))).toBe(':dog:');
+ });
+
+ it('correctly serializes headings', () => {
+ expect(
+ serialize(
+ heading({ level: 1 }, 'Heading 1'),
+ heading({ level: 2 }, 'Heading 2'),
+ heading({ level: 3 }, 'Heading 3'),
+ heading({ level: 4 }, 'Heading 4'),
+ heading({ level: 5 }, 'Heading 5'),
+ heading({ level: 6 }, 'Heading 6'),
+ ),
+ ).toBe(
+ `
+# Heading 1
+
+## Heading 2
+
+### Heading 3
+
+#### Heading 4
+
+##### Heading 5
+
+###### Heading 6
+ `.trim(),
+ );
+ });
+
+ it('correctly serializes horizontal rule', () => {
+ expect(serialize(horizontalRule(), horizontalRule(), horizontalRule())).toBe(
+ `
+---
+
+---
+
+---
+ `.trim(),
+ );
+ });
+
it('correctly serializes an image', () => {
expect(serialize(paragraph(image({ src: 'img.jpg', alt: 'foo bar' })))).toBe(
'![foo bar](img.jpg)',
@@ -173,6 +329,210 @@ describe('markdownSerializer', () => {
).toBe('![this is an image](file.png "foo bar baz")');
});
+ it('correctly serializes bullet list', () => {
+ expect(
+ serialize(
+ bulletList(
+ listItem(paragraph('list item 1')),
+ listItem(paragraph('list item 2')),
+ listItem(paragraph('list item 3')),
+ ),
+ ),
+ ).toBe(
+ `
+* list item 1
+* list item 2
+* list item 3
+ `.trim(),
+ );
+ });
+
+ it('correctly serializes bullet list with different bullet styles', () => {
+ expect(
+ serialize(
+ bulletList(
+ { bullet: '+' },
+ listItem(paragraph('list item 1')),
+ listItem(paragraph('list item 2')),
+ listItem(
+ paragraph('list item 3'),
+ bulletList(
+ { bullet: '-' },
+ listItem(paragraph('sub-list item 1')),
+ listItem(paragraph('sub-list item 2')),
+ ),
+ ),
+ ),
+ ),
+ ).toBe(
+ `
++ list item 1
++ list item 2
++ list item 3
+ - sub-list item 1
+ - sub-list item 2
+ `.trim(),
+ );
+ });
+
+ it('correctly serializes a numeric list', () => {
+ expect(
+ serialize(
+ orderedList(
+ listItem(paragraph('list item 1')),
+ listItem(paragraph('list item 2')),
+ listItem(paragraph('list item 3')),
+ ),
+ ),
+ ).toBe(
+ `
+1. list item 1
+2. list item 2
+3. list item 3
+ `.trim(),
+ );
+ });
+
+ it('correctly serializes a numeric list with parens', () => {
+ expect(
+ serialize(
+ orderedList(
+ { parens: true },
+ listItem(paragraph('list item 1')),
+ listItem(paragraph('list item 2')),
+ listItem(paragraph('list item 3')),
+ ),
+ ),
+ ).toBe(
+ `
+1) list item 1
+2) list item 2
+3) list item 3
+ `.trim(),
+ );
+ });
+
+ it('correctly serializes a numeric list with a different start order', () => {
+ expect(
+ serialize(
+ orderedList(
+ { start: 17 },
+ listItem(paragraph('list item 1')),
+ listItem(paragraph('list item 2')),
+ listItem(paragraph('list item 3')),
+ ),
+ ),
+ ).toBe(
+ `
+17. list item 1
+18. list item 2
+19. list item 3
+ `.trim(),
+ );
+ });
+
+ it('correctly serializes a numeric list with an invalid start order', () => {
+ expect(
+ serialize(
+ orderedList(
+ { start: NaN },
+ listItem(paragraph('list item 1')),
+ listItem(paragraph('list item 2')),
+ listItem(paragraph('list item 3')),
+ ),
+ ),
+ ).toBe(
+ `
+1. list item 1
+2. list item 2
+3. list item 3
+ `.trim(),
+ );
+ });
+
+ it('correctly serializes a bullet list inside an ordered list', () => {
+ expect(
+ serialize(
+ orderedList(
+ { start: 17 },
+ listItem(paragraph('list item 1')),
+ listItem(paragraph('list item 2')),
+ listItem(
+ paragraph('list item 3'),
+ bulletList(
+ listItem(paragraph('sub-list item 1')),
+ listItem(paragraph('sub-list item 2')),
+ ),
+ ),
+ ),
+ ),
+ ).toBe(
+ // notice that 4 space indent works fine in this case,
+ // when it usually wouldn't
+ `
+17. list item 1
+18. list item 2
+19. list item 3
+ * sub-list item 1
+ * sub-list item 2
+ `.trim(),
+ );
+ });
+
+ it('correctly serializes a task list', () => {
+ expect(
+ serialize(
+ taskList(
+ taskItem({ checked: true }, paragraph('list item 1')),
+ taskItem(paragraph('list item 2')),
+ taskItem(
+ paragraph('list item 3'),
+ taskList(
+ taskItem({ checked: true }, paragraph('sub-list item 1')),
+ taskItem(paragraph('sub-list item 2')),
+ ),
+ ),
+ ),
+ ),
+ ).toBe(
+ `
+* [x] list item 1
+* [ ] list item 2
+* [ ] list item 3
+ * [x] sub-list item 1
+ * [ ] sub-list item 2
+ `.trim(),
+ );
+ });
+
+ it('correctly serializes a numeric task list + with start order', () => {
+ expect(
+ serialize(
+ taskList(
+ { numeric: true },
+ taskItem({ checked: true }, paragraph('list item 1')),
+ taskItem(paragraph('list item 2')),
+ taskItem(
+ paragraph('list item 3'),
+ taskList(
+ { numeric: true, start: 1351, parens: true },
+ taskItem({ checked: true }, paragraph('sub-list item 1')),
+ taskItem(paragraph('sub-list item 2')),
+ ),
+ ),
+ ),
+ ),
+ ).toBe(
+ `
+1. [x] list item 1
+2. [ ] list item 2
+3. [ ] list item 3
+ 1351) [x] sub-list item 1
+ 1352) [ ] sub-list item 2
+ `.trim(),
+ );
+ });
+
it('correctly serializes a table with inline content', () => {
expect(
serialize(
diff --git a/spec/frontend/content_editor/services/markdown_sourcemap_spec.js b/spec/frontend/content_editor/services/markdown_sourcemap_spec.js
index 0ef822942ea..a6ebe204078 100644
--- a/spec/frontend/content_editor/services/markdown_sourcemap_spec.js
+++ b/spec/frontend/content_editor/services/markdown_sourcemap_spec.js
@@ -4,9 +4,20 @@ import ListItem from '~/content_editor/extensions/list_item';
import Paragraph from '~/content_editor/extensions/paragraph';
import markdownSerializer from '~/content_editor/services/markdown_serializer';
import { getMarkdownSource } from '~/content_editor/services/markdown_sourcemap';
-import { loadMarkdownApiResult, loadMarkdownApiExample } from '../markdown_processing_examples';
import { createTestEditor, createDocBuilder } from '../test_utils';
+const BULLET_LIST_MARKDOWN = `+ list item 1
++ list item 2
+ - embedded list item 3`;
+const BULLET_LIST_HTML = `<ul data-sourcepos="1:1-3:24" dir="auto">
+ <li data-sourcepos="1:1-1:13">list item 1</li>
+ <li data-sourcepos="2:1-3:24">list item 2
+ <ul data-sourcepos="3:3-3:24">
+ <li data-sourcepos="3:3-3:24">embedded list item 3</li>
+ </ul>
+ </li>
+</ul>`;
+
const SourcemapExtension = Extension.create({
// lets add `source` attribute to every element using `getMarkdownSource`
addGlobalAttributes() {
@@ -44,11 +55,11 @@ const {
describe('content_editor/services/markdown_sourcemap', () => {
it('gets markdown source for a rendered HTML element', async () => {
const deserialized = await markdownSerializer({
- render: () => loadMarkdownApiResult('bullet_list_style_3'),
+ render: () => BULLET_LIST_HTML,
serializerConfig: {},
}).deserialize({
schema: tiptapEditor.schema,
- content: loadMarkdownApiExample('bullet_list_style_3'),
+ content: BULLET_LIST_MARKDOWN,
});
const expected = doc(
diff --git a/spec/frontend/environments/edit_environment_spec.js b/spec/frontend/environments/edit_environment_spec.js
index 3e7f5dd5ff4..2c8c054ccbd 100644
--- a/spec/frontend/environments/edit_environment_spec.js
+++ b/spec/frontend/environments/edit_environment_spec.js
@@ -15,15 +15,12 @@ const DEFAULT_OPTS = {
projectEnvironmentsPath: '/projects/environments',
updateEnvironmentPath: '/proejcts/environments/1',
},
- propsData: { environment: { name: 'foo', externalUrl: 'https://foo.example.com' } },
+ propsData: { environment: { id: '0', name: 'foo', external_url: 'https://foo.example.com' } },
};
describe('~/environments/components/edit.vue', () => {
let wrapper;
let mock;
- let name;
- let url;
- let form;
const createWrapper = (opts = {}) =>
mountExtended(EditEnvironment, {
@@ -34,9 +31,6 @@ describe('~/environments/components/edit.vue', () => {
beforeEach(() => {
mock = new MockAdapter(axios);
wrapper = createWrapper();
- name = wrapper.findByLabelText('Name');
- url = wrapper.findByLabelText('External URL');
- form = wrapper.findByRole('form', { name: 'Edit environment' });
});
afterEach(() => {
@@ -44,19 +38,22 @@ describe('~/environments/components/edit.vue', () => {
wrapper.destroy();
});
+ const findNameInput = () => wrapper.findByLabelText('Name');
+ const findExternalUrlInput = () => wrapper.findByLabelText('External URL');
+ const findForm = () => wrapper.findByRole('form', { name: 'Edit environment' });
+
const showsLoading = () => wrapper.find(GlLoadingIcon).exists();
const submitForm = async (expected, response) => {
mock
.onPut(DEFAULT_OPTS.provide.updateEnvironmentPath, {
- name: expected.name,
external_url: expected.url,
+ id: '0',
})
.reply(...response);
- await name.setValue(expected.name);
- await url.setValue(expected.url);
+ await findExternalUrlInput().setValue(expected.url);
- await form.trigger('submit');
+ await findForm().trigger('submit');
await waitForPromises();
};
@@ -65,18 +62,8 @@ describe('~/environments/components/edit.vue', () => {
expect(header.exists()).toBe(true);
});
- it.each`
- input | value
- ${() => name} | ${'test'}
- ${() => url} | ${'https://example.org'}
- `('it changes the value of the input to $value', async ({ input, value }) => {
- await input().setValue(value);
-
- expect(input().element.value).toBe(value);
- });
-
it('shows loader after form is submitted', async () => {
- const expected = { name: 'test', url: 'https://google.ca' };
+ const expected = { url: 'https://google.ca' };
expect(showsLoading()).toBe(false);
@@ -86,7 +73,7 @@ describe('~/environments/components/edit.vue', () => {
});
it('submits the updated environment on submit', async () => {
- const expected = { name: 'test', url: 'https://google.ca' };
+ const expected = { url: 'https://google.ca' };
await submitForm(expected, [200, { path: '/test' }]);
@@ -94,11 +81,24 @@ describe('~/environments/components/edit.vue', () => {
});
it('shows errors on error', async () => {
- const expected = { name: 'test', url: 'https://google.ca' };
+ const expected = { url: 'https://google.ca' };
- await submitForm(expected, [400, { message: ['name taken'] }]);
+ await submitForm(expected, [400, { message: ['uh oh!'] }]);
- expect(createFlash).toHaveBeenCalledWith({ message: 'name taken' });
+ expect(createFlash).toHaveBeenCalledWith({ message: 'uh oh!' });
expect(showsLoading()).toBe(false);
});
+
+ it('renders a disabled "Name" field', () => {
+ const nameInput = findNameInput();
+
+ expect(nameInput.attributes().disabled).toBe('disabled');
+ expect(nameInput.element.value).toBe('foo');
+ });
+
+ it('renders an "External URL" field', () => {
+ const urlInput = findExternalUrlInput();
+
+ expect(urlInput.element.value).toBe('https://foo.example.com');
+ });
});
diff --git a/spec/frontend/environments/environment_form_spec.js b/spec/frontend/environments/environment_form_spec.js
index ed8fda71dab..f1af08bcf32 100644
--- a/spec/frontend/environments/environment_form_spec.js
+++ b/spec/frontend/environments/environment_form_spec.js
@@ -102,4 +102,52 @@ describe('~/environments/components/form.vue', () => {
wrapper = createWrapper({ loading: true });
expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
});
+ describe('when a new environment is being created', () => {
+ beforeEach(() => {
+ wrapper = createWrapper({
+ environment: {
+ name: '',
+ externalUrl: '',
+ },
+ });
+ });
+
+ it('renders an enabled "Name" field', () => {
+ const nameInput = wrapper.findByLabelText('Name');
+
+ expect(nameInput.attributes().disabled).toBeUndefined();
+ expect(nameInput.element.value).toBe('');
+ });
+
+ it('renders an "External URL" field', () => {
+ const urlInput = wrapper.findByLabelText('External URL');
+
+ expect(urlInput.element.value).toBe('');
+ });
+ });
+
+ describe('when an existing environment is being edited', () => {
+ beforeEach(() => {
+ wrapper = createWrapper({
+ environment: {
+ id: 1,
+ name: 'test',
+ externalUrl: 'https://example.com',
+ },
+ });
+ });
+
+ it('renders a disabled "Name" field', () => {
+ const nameInput = wrapper.findByLabelText('Name');
+
+ expect(nameInput.attributes().disabled).toBe('disabled');
+ expect(nameInput.element.value).toBe('test');
+ });
+
+ it('renders an "External URL" field', () => {
+ const urlInput = wrapper.findByLabelText('External URL');
+
+ expect(urlInput.element.value).toBe('https://example.com');
+ });
+ });
});
diff --git a/spec/frontend/fixtures/api_markdown.yml b/spec/frontend/fixtures/api_markdown.yml
index ff9da33c116..32bbb5db745 100644
--- a/spec/frontend/fixtures/api_markdown.yml
+++ b/spec/frontend/fixtures/api_markdown.yml
@@ -99,6 +99,11 @@
1. list item 1
2. list item 2
3. list item 3
+- name: ordered_list_with_start_order
+ markdown: |-
+ 134. list item 1
+ 135. list item 2
+ 136. list item 3
- name: task_list
markdown: |-
* [x] hello
@@ -115,6 +120,11 @@
1. [ ] of nested
1. [x] task list
2. [ ] items
+- name: ordered_task_list_with_order
+ markdown: |-
+ 4893. [x] hello
+ 4894. [x] world
+ 4895. [ ] example
- name: image
markdown: '![alt text](https://gitlab.com/logo.png)'
- name: hard_break
diff --git a/spec/frontend/lib/utils/dom_utils_spec.js b/spec/frontend/lib/utils/dom_utils_spec.js
index 7c4c20e651f..cb8b1c7ca9a 100644
--- a/spec/frontend/lib/utils/dom_utils_spec.js
+++ b/spec/frontend/lib/utils/dom_utils_spec.js
@@ -5,6 +5,7 @@ import {
parseBooleanDataAttributes,
isElementVisible,
isElementHidden,
+ getParents,
} from '~/lib/utils/dom_utils';
const TEST_MARGIN = 5;
@@ -193,4 +194,18 @@ describe('DOM Utils', () => {
});
},
);
+
+ describe('getParents', () => {
+ it('gets all parents of an element', () => {
+ const el = document.createElement('div');
+ el.innerHTML = '<p><span><strong><mark>hello world';
+
+ expect(getParents(el.querySelector('mark'))).toEqual([
+ el.querySelector('strong'),
+ el.querySelector('span'),
+ el.querySelector('p'),
+ el,
+ ]);
+ });
+ });
});