67 lines
2.6 KiB
TypeScript
67 lines
2.6 KiB
TypeScript
/**
|
|||
|
|
* The admin panel does not import field components directly. Payload sends the
|
||
|
|
* client a *path* for each one — a richText field's is
|
||
|
|
* `@payloadcms/richtext-lexical/rsc#RscEntryLexicalField` — and resolves it
|
||
|
|
* through this generated map. An entry that is missing from the map is not an
|
||
|
|
* error the panel reports: the field simply does not render.
|
||
|
|
*
|
||
|
|
* That failure is quietly awful, because `required: true` is enforced on the
|
||
|
|
* server regardless. A writer gets a new-post form with no Content editor and
|
||
|
|
* a save that refuses on a field they were never shown.
|
||
|
|
*
|
||
|
|
* The map is generated by `npx payload generate:importmap`, so it drifts every
|
||
|
|
* time a field or a lexical feature is added and nobody re-runs it. These
|
||
|
|
* assert the entries the current config needs.
|
||
|
|
*/
|
||
|
|
import fs from 'fs';
|
||
|
|
import path from 'path';
|
||
|
|
|
||
|
|
const MAP = fs.readFileSync(
|
||
|
|
path.join(__dirname, '..', '..', 'app', '(payload)', 'admin', 'importMap.js'),
|
||
|
|
'utf8',
|
||
|
|
);
|
||
|
|
const POSTS = fs.readFileSync(
|
||
|
|
path.join(__dirname, '..', '..', 'collections', 'Posts.ts'),
|
||
|
|
'utf8',
|
||
|
|
);
|
||
|
|
|
||
|
|
describe('admin import map', () => {
|
||
|
|
it('resolves the richText field, so Content renders in the editor', () => {
|
||
|
|
// Guarded because Posts.content is required: without this entry the field
|
||
|
|
// is invisible and the post is unsaveable.
|
||
|
|
expect(POSTS).toMatch(/type:\s*'richText'/);
|
||
|
|
expect(MAP).toContain('@payloadcms/richtext-lexical/rsc#RscEntryLexicalField');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('resolves the richText cell, so the list view can render the column', () => {
|
||
|
|
expect(MAP).toContain('@payloadcms/richtext-lexical/rsc#RscEntryLexicalCell');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('resolves the diff component, which the drafts UI needs', () => {
|
||
|
|
// versions.drafts is on, so the panel offers version comparison.
|
||
|
|
expect(POSTS).toMatch(/drafts:\s*true/);
|
||
|
|
expect(MAP).toContain('@payloadcms/richtext-lexical/rsc#LexicalDiffComponent');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('resolves BlocksFeature, so the Callout block is insertable', () => {
|
||
|
|
expect(POSTS).toContain('BlocksFeature');
|
||
|
|
expect(MAP).toContain('@payloadcms/richtext-lexical/client#BlocksFeatureClient');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('resolves the default toolbar features the editor is built with', () => {
|
||
|
|
// defaultFeatures is spread into the editor config; each one contributes a
|
||
|
|
// client component the toolbar cannot render without.
|
||
|
|
for (const feature of [
|
||
|
|
'BoldFeatureClient',
|
||
|
|
'ItalicFeatureClient',
|
||
|
|
'HeadingFeatureClient',
|
||
|
|
'LinkFeatureClient',
|
||
|
|
'UploadFeatureClient',
|
||
|
|
'UnorderedListFeatureClient',
|
||
|
|
'OrderedListFeatureClient',
|
||
|
|
'InlineToolbarFeatureClient',
|
||
|
|
]) {
|
||
|
|
expect(MAP).toContain(`@payloadcms/richtext-lexical/client#${feature}`);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
});
|