textarea <=> steps

This commit is contained in:
Julien Calixte
2023-04-08 18:33:12 +02:00
parent 9870caac1f
commit b6059aa666
3 changed files with 137 additions and 2 deletions

View File

@@ -1,18 +1,36 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref } from 'vue'
import {
adaptStepsToTextarea,
adaptTextareaToSteps
} from '../infra/adaptStepsToTextarea'
import type { Step } from '../models/step' import type { Step } from '../models/step'
defineProps<{ const props = defineProps<{
modelValue: Step[] modelValue: Step[]
}>() }>()
const emit = defineEmits<{ const emit = defineEmits<{
(event: 'update:modelValue', payload: Step[]): void (event: 'update:modelValue', payload: Step[]): void
}>() }>()
const rawSteps = ref(adaptStepsToTextarea(props.modelValue))
const stepsTextarea = computed({
get() {
return rawSteps.value
},
set(value) {
rawSteps.value = value
emit('update:modelValue', adaptTextareaToSteps(value))
}
})
</script> </script>
<template> <template>
<div class="step-input"> <div class="step-input">
<div>textarea</div> <textarea v-model="stepsTextarea"></textarea>
<div>beautiful data</div> <div>beautiful data</div>
</div> </div>
</template> </template>

View File

@@ -0,0 +1,79 @@
import { describe, expect, it } from 'vitest'
import { createStepFixture } from '../models/step.fixture'
import {
adaptStepsToTextarea,
adaptTextareaToSteps
} from './adaptStepsToTextarea'
describe('adapt steps to textarea value', () => {
it('returns a string with the listed steps', () => {
const steps = [
createStepFixture(),
createStepFixture(),
createStepFixture(),
createStepFixture()
]
const stepsInTextarea = steps
.map((step) => `- ${step.title} | ${step.estimation}`)
.join('\n')
expect(adaptStepsToTextarea(steps)).toEqual(stepsInTextarea)
})
it('returns a list of steps from a textarea value', () => {
const stepsInTextarea = `- step 1 | 3
- step 2 | 4
- step 3 | 5`
const expectedSteps = [
createStepFixture({
id: expect.any(String),
title: 'step 1',
estimation: 3
}),
createStepFixture({
id: expect.any(String),
title: 'step 2',
estimation: 4
}),
createStepFixture({
id: expect.any(String),
title: 'step 3',
estimation: 5
})
]
expect(adaptTextareaToSteps(stepsInTextarea)).toEqual(expectedSteps)
})
it('fallbacks to 0 for the estimation if there is no estimation', () => {
const stepInTextarea = '- step 1'
const expectedStep = createStepFixture({
id: expect.any(String),
title: 'step 1',
estimation: 0
})
expect(adaptTextareaToSteps(stepInTextarea)).toEqual([expectedStep])
})
it('fallbacks to 0 for the estimation if it can not read the number', () => {
const stepInTextarea = '- step 1 | not an estimation'
const expectedStep = createStepFixture({
id: expect.any(String),
title: 'step 1',
estimation: 0
})
expect(adaptTextareaToSteps(stepInTextarea)).toEqual([expectedStep])
})
it('does not create a step with an empty title', () => {
const stepInTextArea = '\n-'
expect(adaptTextareaToSteps(stepInTextArea)).toEqual([])
})
})

View File

@@ -0,0 +1,38 @@
import { createUuid } from '@/shared/create-uuid'
import { Step } from '../models/step'
export const adaptStepsToTextarea = (steps: Step[]) =>
steps.map((step) => `- ${step.title} | ${step.estimation}`).join('\n')
const extractTitleAndEstimationFromStep = (
rawStep: string
): [string, number] => {
const [rawTitle, rawEstimation] = rawStep
.trim()
.replace(/^-\s*/, '')
.split('|')
const title = rawTitle.trim()
const estimationString = (rawEstimation || '').trim()
const estimation = Number(estimationString)
if (isNaN(estimation)) {
return [title, 0]
}
return [title, estimation]
}
export const adaptTextareaToSteps = (textareaValue: string): Step[] =>
textareaValue
.split('\n')
.map((rawStep) => {
const [title, estimation] = extractTitleAndEstimationFromStep(rawStep)
if (!title) {
return null
}
return new Step(createUuid(), title, estimation)
})
.filter((step) => step !== null) as Step[]