Skip to content

Commit 35a1ec1

Browse files
committed
test: create new BlockParagraph component
1 parent 44e53e3 commit 35a1ec1

File tree

4 files changed

+136
-2
lines changed

4 files changed

+136
-2
lines changed

packages/app/__tests__/fixtures/component.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@ import { ComponentMountingOptions, VueWrapper, mount } from '@vue/test-utils'
22
import { DefineComponent } from 'vue'
33
import merge from 'lodash/merge'
44

5-
export function useMountWrapper<T extends DefineComponent<any, any, any, any, any>>(component: T) {
5+
export function useMountWrapper<T extends DefineComponent<any, any, any, any, any>>(
6+
component: T,
7+
defaultOptions?: ComponentMountingOptions<T>
8+
) {
69
const state = {
710
wrapper: null as VueWrapper<InstanceType<T>> | null,
811
mount: (options?: ComponentMountingOptions<T>) => {
9-
state.wrapper = mount(component, merge(options))
12+
state.wrapper = mount(component, merge(options, defaultOptions))
1013

1114
return state.wrapper!
1215
},
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { useMountWrapper } from '__tests__/fixtures/component'
2+
import { afterEach, describe, expect, it, vi } from 'vitest'
3+
4+
import BlockParagraph from './BlockParagraph.vue'
5+
import HTMLContentEditable from './HTMLContentEditable.vue'
6+
import { createNodeParagraphFromHtml } from '../composables/helpers'
7+
8+
describe('BlockParagraph', () => {
9+
const component = useMountWrapper(BlockParagraph, {
10+
shallow: true,
11+
})
12+
13+
afterEach(component.unmount)
14+
15+
function findHTMLContentEditable() {
16+
return component.wrapper!.findComponent(HTMLContentEditable)
17+
}
18+
19+
it('should pass node as html to HTMLContentEditable component', () => {
20+
component.mount({
21+
props: {
22+
modelValue: createNodeParagraphFromHtml('Test <strong>bold</strong>'),
23+
},
24+
})
25+
26+
const editable = findHTMLContentEditable()
27+
28+
expect(editable.exists()).toBe(true)
29+
30+
expect(editable.props('modelValue')).toBe('<p>Test <strong>bold</strong></p>')
31+
})
32+
33+
it('should when html changes, emit update event with correct format', async () => {
34+
const spy = vi.fn()
35+
36+
component.mount({
37+
props: {
38+
'modelValue': createNodeParagraphFromHtml('Test <strong>bold</strong>'),
39+
'onUpdate:model-value': spy,
40+
},
41+
})
42+
43+
const editable = findHTMLContentEditable()
44+
45+
await editable.setValue('Test <strong>bold</strong> update')
46+
47+
expect(spy).toHaveBeenCalledOnce()
48+
49+
expect(spy).toHaveBeenCalledWith(
50+
createNodeParagraphFromHtml('Test <strong>bold</strong> update')
51+
)
52+
})
53+
54+
it.todo('should focus HTMLContentEditable when block is selected')
55+
56+
it.todo('should blur HTMLContentEditable area when block is selected')
57+
58+
it.todo('should emit update event when ToolbarTextFormat modifies the content')
59+
})
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<script setup lang="ts">
2+
import { MarkdownNodeParagraph } from '@language-kit/markdown'
3+
import HTMLContentEditable from './HTMLContentEditable.vue'
4+
import { createNodeParagraphFromHtml } from '../composables/helpers'
5+
6+
const model = defineModel({
7+
type: MarkdownNodeParagraph,
8+
required: true,
9+
})
10+
11+
const html = ref('')
12+
13+
function load() {
14+
html.value = model.value.toHtml()
15+
}
16+
17+
function onHtmlUpdate(payload: string) {
18+
html.value = payload
19+
20+
const node = createNodeParagraphFromHtml(payload)
21+
22+
model.value = node
23+
}
24+
25+
watch(model, load, { immediate: true })
26+
</script>
27+
<template>
28+
<div>
29+
<HTMLContentEditable :model-value="html" @update:model-value="onHtmlUpdate" />
30+
</div>
31+
</template>
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import {
2+
MarkdownNodeParagraph,
3+
MarkdownParser,
4+
MarkdownProcessorParagraph,
5+
} from '@language-kit/markdown'
6+
7+
const parser = new MarkdownParser()
8+
9+
export function createNodeParagraphFromHtml(payload: string) {
10+
const node = new MarkdownNodeParagraph()
11+
12+
let text = payload
13+
14+
if (text.startsWith('<p>')) {
15+
// replace <p>{content}</p> > {content}
16+
text = payload.replace(/^<p>(.*)<\/p>$/, '$1')
17+
}
18+
19+
// replace <strong>Text</strong> to **Text**
20+
text = text.replaceAll(/<strong>([^<]+)<\/strong>/g, '**$1**')
21+
22+
// replace <em>Text</em> to *Text*
23+
text = text.replaceAll(/<em>([^<]+)<\/em>/g, '*$1*')
24+
25+
// replace <s>Text</s> to ~~Text~~
26+
text = text.replaceAll(/<s>([^<]+)<\/s>/g, '~~$1~~')
27+
28+
// replace <span {attrs}>Text</span> to [Text]{attrs}
29+
text = text.replaceAll(/<span\s+([^>]+)>([^<]+)<\/span>/g, '[$2]{ $1 }')
30+
31+
node.children = parser.toNodes(text, {
32+
lexer: {
33+
includeEndOfFileToken: false,
34+
},
35+
processors: {
36+
exclude: [MarkdownProcessorParagraph],
37+
},
38+
})
39+
40+
return node
41+
}

0 commit comments

Comments
 (0)