TASKS-1823 WebManager module
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
import { test } from '@japa/runner'
|
||||
import FormSourceBuilder from '#services/module_generator/builders/form_source_builder'
|
||||
import {
|
||||
ModuleFieldOption,
|
||||
ModuleFieldType,
|
||||
ModuleLayoutConfig,
|
||||
} from '#services/module_generator/types'
|
||||
|
||||
const layout = (type: ModuleFieldType, options: ModuleFieldOption[]): ModuleLayoutConfig => ({
|
||||
grid: [
|
||||
{
|
||||
id: '1',
|
||||
row: 0,
|
||||
col: 0,
|
||||
rowSpan: 1,
|
||||
colSpan: 1,
|
||||
isEmpty: false,
|
||||
mergeTo: null,
|
||||
body: {
|
||||
dbColumn: 'category',
|
||||
type,
|
||||
label: 'Category',
|
||||
placeholder: 'Pick one',
|
||||
required: false,
|
||||
options,
|
||||
},
|
||||
},
|
||||
],
|
||||
rows: 1,
|
||||
cols: 1,
|
||||
selectedCells: [],
|
||||
size: 'dialog-default',
|
||||
})
|
||||
|
||||
test.group('FormSourceBuilder grouped options', () => {
|
||||
test('emits combobox groups bucketed by group name, ungrouped options in an unlabeled group', ({
|
||||
assert,
|
||||
}) => {
|
||||
const source = FormSourceBuilder.buildComponent(
|
||||
layout(ModuleFieldType.COMBOBOX, [
|
||||
{ label: 'Apple', value: 'apple', group: 'Fruits' },
|
||||
{ label: 'Carrot', value: 'carrot', group: 'Veggies' },
|
||||
{ label: 'Other', value: 'other' },
|
||||
{ label: 'Pear', value: 'pear', group: 'Fruits' },
|
||||
])
|
||||
)
|
||||
|
||||
assert.include(
|
||||
source,
|
||||
'groups={[{"label":"Fruits","options":[{"label":"Apple","value":"apple"},{"label":"Pear","value":"pear"}]},{"label":"Veggies","options":[{"label":"Carrot","value":"carrot"}]},{"options":[{"label":"Other","value":"other"}]}]}'
|
||||
)
|
||||
assert.include(source, 'InputCombobox')
|
||||
})
|
||||
|
||||
test('emits multiselect heading groups when any option has a group', ({ assert }) => {
|
||||
const source = FormSourceBuilder.buildComponent(
|
||||
layout(ModuleFieldType.MULTISELECT, [
|
||||
{ label: 'Apple', value: 'apple', group: 'Fruits' },
|
||||
{ label: 'Other', value: 'other' },
|
||||
])
|
||||
)
|
||||
|
||||
assert.include(
|
||||
source,
|
||||
'options={[{"heading":"Fruits","options":[{"label":"Apple","value":"apple"}]},{"heading":"","options":[{"label":"Other","value":"other"}]}]}'
|
||||
)
|
||||
})
|
||||
|
||||
test('keeps multiselect options flat when no groups are set', ({ assert }) => {
|
||||
const source = FormSourceBuilder.buildComponent(
|
||||
layout(ModuleFieldType.MULTISELECT, [
|
||||
{ label: 'Apple', value: 'apple', group: '' },
|
||||
{ label: 'Other', value: 'other' },
|
||||
])
|
||||
)
|
||||
|
||||
assert.include(
|
||||
source,
|
||||
'options={[{"label":"Apple","value":"apple"},{"label":"Other","value":"other"}]}'
|
||||
)
|
||||
})
|
||||
|
||||
test('strips group from flat-only fields', ({ assert }) => {
|
||||
const source = FormSourceBuilder.buildComponent(
|
||||
layout(ModuleFieldType.SELECT, [{ label: 'Apple', value: 'apple', group: 'Fruits' }])
|
||||
)
|
||||
|
||||
assert.include(source, 'options={[{"label":"Apple","value":"apple"}]}')
|
||||
assert.notInclude(source, '"group"')
|
||||
})
|
||||
|
||||
test('imports only the composed components present in the emitted JSX', ({ assert }) => {
|
||||
const source = FormSourceBuilder.buildComponent(layout(ModuleFieldType.TEXT, []))
|
||||
|
||||
assert.include(
|
||||
source,
|
||||
"import { FormElement, FormGrid, GridElement, InputText } from '#shared/forms/composed';"
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,76 @@
|
||||
import { test } from '@japa/runner'
|
||||
import { existsSync, mkdtempSync, readFileSync, rmSync } from 'node:fs'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import { writeFrontendModule } from '#services/module_generator/writers/frontend_module_writer'
|
||||
|
||||
const TEMPLATE_DIR = join(process.cwd(), 'app', 'templates', 'frontend', 'module')
|
||||
|
||||
test.group('writeFrontendModule', (group) => {
|
||||
let outDir: string
|
||||
|
||||
group.each.setup(() => {
|
||||
outDir = mkdtempSync(join(tmpdir(), 'module-writer-'))
|
||||
return () => rmSync(outDir, { recursive: true, force: true })
|
||||
})
|
||||
|
||||
test('renders hbs files with context and strips the extension', ({ assert }) => {
|
||||
writeFrontendModule({
|
||||
templateDir: TEMPLATE_DIR,
|
||||
outDir,
|
||||
context: {
|
||||
name: 'post',
|
||||
fields: [{ name: 'title', type: 'string' }],
|
||||
},
|
||||
overrides: {},
|
||||
})
|
||||
|
||||
assert.isFalse(existsSync(join(outDir, 'config', 'meta.ts.hbs')))
|
||||
const meta = readFileSync(join(outDir, 'config', 'meta.ts'), 'utf8')
|
||||
assert.include(meta, "export const MODULE_NAME = 'post'")
|
||||
|
||||
const entity = readFileSync(join(outDir, 'entities', 'Entity.ts'), 'utf8')
|
||||
assert.include(entity, 'title: string')
|
||||
})
|
||||
|
||||
test('copies non-hbs files verbatim, preserving nesting', ({ assert }) => {
|
||||
writeFrontendModule({
|
||||
templateDir: TEMPLATE_DIR,
|
||||
outDir,
|
||||
context: { name: 'x' },
|
||||
overrides: {},
|
||||
})
|
||||
|
||||
const template = readFileSync(join(TEMPLATE_DIR, 'view', 'widgets', 'DataTable.tsx'), 'utf8')
|
||||
const copied = readFileSync(join(outDir, 'view', 'widgets', 'DataTable.tsx'), 'utf8')
|
||||
assert.equal(copied, template)
|
||||
})
|
||||
|
||||
test('writes overrides on top of the scaffold and keeps defaults for null overrides', ({
|
||||
assert,
|
||||
}) => {
|
||||
writeFrontendModule({
|
||||
templateDir: TEMPLATE_DIR,
|
||||
outDir,
|
||||
context: { name: 'x' },
|
||||
overrides: {
|
||||
'view/widgets/DataTable.tsx': '// generated',
|
||||
'view/forms/MainForm/Component.tsx': null,
|
||||
},
|
||||
})
|
||||
|
||||
assert.equal(
|
||||
readFileSync(join(outDir, 'view', 'widgets', 'DataTable.tsx'), 'utf8'),
|
||||
'// generated'
|
||||
)
|
||||
|
||||
const scaffoldForm = readFileSync(
|
||||
join(TEMPLATE_DIR, 'view', 'forms', 'MainForm', 'Component.tsx'),
|
||||
'utf8'
|
||||
)
|
||||
assert.equal(
|
||||
readFileSync(join(outDir, 'view', 'forms', 'MainForm', 'Component.tsx'), 'utf8'),
|
||||
scaffoldForm
|
||||
)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user