summaryrefslogtreecommitdiff
path: root/spec/frontend/content_editor/markdown_processing_spec_helper.js
blob: 6f10f294fb0851c5b4430b7a639f8cd5074fe1e3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import fs from 'fs';
import jsYaml from 'js-yaml';
import { memoize } from 'lodash';
import MockAdapter from 'axios-mock-adapter';
import axios from 'axios';
import { createContentEditor } from '~/content_editor';
import httpStatus from '~/lib/utils/http_status';

const getFocusedMarkdownExamples = memoize(
  () => process.env.FOCUSED_MARKDOWN_EXAMPLES?.split(',') || [],
);

const includeExample = ({ name }) => {
  const focusedMarkdownExamples = getFocusedMarkdownExamples();
  if (!focusedMarkdownExamples.length) {
    return true;
  }
  return focusedMarkdownExamples.includes(name);
};

const getPendingReason = (pendingStringOrObject) => {
  if (!pendingStringOrObject) {
    return null;
  }
  if (typeof pendingStringOrObject === 'string') {
    return pendingStringOrObject;
  }
  if (pendingStringOrObject.frontend) {
    return pendingStringOrObject.frontend;
  }

  return null;
};

const loadMarkdownApiExamples = (markdownYamlPath) => {
  const apiMarkdownYamlText = fs.readFileSync(markdownYamlPath);
  const apiMarkdownExampleObjects = jsYaml.safeLoad(apiMarkdownYamlText);

  return apiMarkdownExampleObjects
    .filter(includeExample)
    .map(({ name, pending, markdown, html }) => [
      name,
      { pendingReason: getPendingReason(pending), markdown, html },
    ]);
};

const testSerializesHtmlToMarkdownForElement = async ({ markdown, html }) => {
  const mock = new MockAdapter(axios);

  // Ignore any API requests from the suggestions plugin
  mock.onGet().reply(httpStatus.OK, []);

  const contentEditor = createContentEditor({
    // Overwrite renderMarkdown to always return this specific html
    renderMarkdown: () => html,
  });

  await contentEditor.setSerializedContent(markdown);

  // This serializes the ContentEditor document, which was based on the HTML, to markdown
  const serializedContent = contentEditor.getSerializedContent();

  // Assert that the markdown we ended up with after sending it through all the ContentEditor
  // plumbing matches the original markdown from the YAML.
  expect(serializedContent.trim()).toBe(markdown.trim());

  mock.restore();
};

// describeMarkdownProcesssing
//
// This is used to dynamically generate examples (for both CE and EE) to ensure
// we generate same markdown that was provided to Markdown API.
//
// eslint-disable-next-line jest/no-export
export const describeMarkdownProcessing = (description, markdownYamlPath) => {
  const examples = loadMarkdownApiExamples(markdownYamlPath);

  describe(description, () => {
    describe.each(examples)('%s', (name, { pendingReason, ...example }) => {
      const exampleName = 'correctly serializes HTML to markdown';
      if (pendingReason) {
        it.todo(`${exampleName}: ${pendingReason}`);
        return;
      }

      it(`${exampleName}`, async () => {
        await testSerializesHtmlToMarkdownForElement(example);
      });
    });
  });
};