Emdash source with visual editor image upload fix
Fixes: 1. media.ts: wrap placeholder generation in try-catch 2. toolbar.ts: check r.ok, display error message in popover
This commit is contained in:
114
e2e/fixture/.emdash/seed.json
Normal file
114
e2e/fixture/.emdash/seed.json
Normal file
@@ -0,0 +1,114 @@
|
||||
{
|
||||
"$schema": "https://emdashcms.com/seed.schema.json",
|
||||
"version": "1",
|
||||
"meta": {
|
||||
"name": "E2E Test Fixture",
|
||||
"description": "Schema for E2E tests"
|
||||
},
|
||||
"taxonomies": [
|
||||
{
|
||||
"name": "category",
|
||||
"label": "Categories",
|
||||
"labelSingular": "Category",
|
||||
"hierarchical": true,
|
||||
"collections": ["posts"],
|
||||
"terms": [
|
||||
{ "slug": "news", "label": "News" },
|
||||
{ "slug": "tutorials", "label": "Tutorials" },
|
||||
{ "slug": "opinion", "label": "Opinion" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "tag",
|
||||
"label": "Tags",
|
||||
"labelSingular": "Tag",
|
||||
"hierarchical": false,
|
||||
"collections": ["posts"]
|
||||
}
|
||||
],
|
||||
"sections": [
|
||||
{
|
||||
"slug": "hero",
|
||||
"title": "Hero Section",
|
||||
"description": "Main hero area",
|
||||
"content": [
|
||||
{
|
||||
"_type": "block",
|
||||
"_key": "b1",
|
||||
"style": "normal",
|
||||
"children": [{ "_type": "span", "_key": "s1", "text": "Welcome to our site" }],
|
||||
"markDefs": []
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"collections": [
|
||||
{
|
||||
"slug": "posts",
|
||||
"label": "Posts",
|
||||
"labelSingular": "Post",
|
||||
"supports": ["drafts", "revisions", "search"],
|
||||
"commentsEnabled": true,
|
||||
"fields": [
|
||||
{
|
||||
"slug": "title",
|
||||
"label": "Title",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"searchable": true
|
||||
},
|
||||
{
|
||||
"slug": "featured_image",
|
||||
"label": "Featured Image",
|
||||
"type": "image"
|
||||
},
|
||||
{
|
||||
"slug": "body",
|
||||
"label": "Body",
|
||||
"type": "portableText",
|
||||
"searchable": true
|
||||
},
|
||||
{
|
||||
"slug": "excerpt",
|
||||
"label": "Excerpt",
|
||||
"type": "text",
|
||||
"searchable": true
|
||||
},
|
||||
{
|
||||
"slug": "theme_color",
|
||||
"label": "Theme Color",
|
||||
"type": "string",
|
||||
"widget": "color:picker"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"slug": "pages",
|
||||
"label": "Pages",
|
||||
"labelSingular": "Page",
|
||||
"supports": ["drafts", "revisions", "search"],
|
||||
"fields": [
|
||||
{
|
||||
"slug": "title",
|
||||
"label": "Title",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"searchable": true
|
||||
},
|
||||
{
|
||||
"slug": "body",
|
||||
"label": "Body",
|
||||
"type": "portableText",
|
||||
"searchable": true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"bylines": [
|
||||
{
|
||||
"id": "fixture-editorial",
|
||||
"slug": "fixture-editorial",
|
||||
"displayName": "Fixture Editorial"
|
||||
}
|
||||
]
|
||||
}
|
||||
40
e2e/fixture/astro.config.mjs
Normal file
40
e2e/fixture/astro.config.mjs
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Minimal Astro config for Playwright e2e tests.
|
||||
*
|
||||
* Uses env vars for the database path and optional marketplace URL
|
||||
* so each test run gets an isolated database.
|
||||
*/
|
||||
import node from "@astrojs/node";
|
||||
import react from "@astrojs/react";
|
||||
import { colorPlugin } from "@emdash-cms/plugin-color";
|
||||
import { defineConfig } from "astro/config";
|
||||
import emdash from "emdash/astro";
|
||||
import { sqlite } from "emdash/db";
|
||||
|
||||
const dbUrl = process.env.EMDASH_TEST_DB || "file:./test.db";
|
||||
const marketplaceUrl = process.env.EMDASH_MARKETPLACE_URL || undefined;
|
||||
|
||||
export default defineConfig({
|
||||
output: "server",
|
||||
adapter: node({ mode: "standalone" }),
|
||||
integrations: [
|
||||
react(),
|
||||
emdash({
|
||||
database: sqlite({ url: dbUrl }),
|
||||
plugins: [colorPlugin()],
|
||||
marketplace: marketplaceUrl,
|
||||
sandboxRunner: marketplaceUrl ? "./noop-sandbox.mjs" : undefined,
|
||||
}),
|
||||
],
|
||||
i18n: {
|
||||
defaultLocale: "en",
|
||||
locales: ["en", "fr", "es"],
|
||||
fallback: { fr: "en", es: "en" },
|
||||
},
|
||||
devToolbar: { enabled: false },
|
||||
vite: {
|
||||
server: {
|
||||
fs: { strict: false },
|
||||
},
|
||||
},
|
||||
});
|
||||
40
e2e/fixture/emdash-env.d.ts
vendored
Normal file
40
e2e/fixture/emdash-env.d.ts
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
// Generated by EmDash on dev server start
|
||||
// Do not edit manually
|
||||
|
||||
/// <reference types="emdash/locals" />
|
||||
|
||||
import type { ContentBylineCredit, PortableTextBlock } from "emdash";
|
||||
|
||||
export interface Page {
|
||||
id: string;
|
||||
slug: string | null;
|
||||
status: string;
|
||||
title: string;
|
||||
body?: PortableTextBlock[];
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
publishedAt: Date | null;
|
||||
bylines?: ContentBylineCredit[];
|
||||
}
|
||||
|
||||
export interface Post {
|
||||
id: string;
|
||||
slug: string | null;
|
||||
status: string;
|
||||
title: string;
|
||||
featured_image?: { id: string; src?: string; alt?: string; width?: number; height?: number };
|
||||
body?: PortableTextBlock[];
|
||||
excerpt?: string;
|
||||
theme_color?: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
publishedAt: Date | null;
|
||||
bylines?: ContentBylineCredit[];
|
||||
}
|
||||
|
||||
declare module "emdash" {
|
||||
interface EmDashCollections {
|
||||
pages: Page;
|
||||
posts: Post;
|
||||
}
|
||||
}
|
||||
10
e2e/fixture/noop-sandbox.mjs
Normal file
10
e2e/fixture/noop-sandbox.mjs
Normal file
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Noop sandbox runner for e2e tests.
|
||||
*
|
||||
* The marketplace admin pages only need `marketplace: true` in the manifest
|
||||
* to render browse/detail UI. The sandbox runner is only used at install time.
|
||||
* This stub satisfies the config validation without importing cloudflare:workers.
|
||||
*/
|
||||
import { createNoopSandboxRunner } from "emdash";
|
||||
|
||||
export { createNoopSandboxRunner as createSandboxRunner };
|
||||
16
e2e/fixture/package.json
Normal file
16
e2e/fixture/package.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "emdash-e2e-fixture",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@astrojs/node": "catalog:",
|
||||
"@astrojs/react": "catalog:",
|
||||
"@emdash-cms/auth": "workspace:*",
|
||||
"@emdash-cms/plugin-color": "workspace:*",
|
||||
"astro": "catalog:",
|
||||
"better-sqlite3": "catalog:",
|
||||
"emdash": "workspace:*",
|
||||
"react": "catalog:",
|
||||
"react-dom": "catalog:"
|
||||
}
|
||||
}
|
||||
6
e2e/fixture/src/live.config.ts
Normal file
6
e2e/fixture/src/live.config.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { defineLiveCollection } from "astro:content";
|
||||
import { emdashLoader } from "emdash/runtime";
|
||||
|
||||
export const collections = {
|
||||
_emdash: defineLiveCollection({ loader: emdashLoader() }),
|
||||
};
|
||||
21
e2e/fixture/src/pages/index.astro
Normal file
21
e2e/fixture/src/pages/index.astro
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
import { getEmDashCollection } from "emdash";
|
||||
const { entries: posts } = await getEmDashCollection("posts");
|
||||
---
|
||||
|
||||
<html>
|
||||
<body>
|
||||
<h1>Posts</h1>
|
||||
<ul id="post-list">
|
||||
{
|
||||
posts.map((p) => (
|
||||
<li>
|
||||
<a href={`/posts/${p.id}`}>{p.data.title}</a>
|
||||
{p.data.excerpt && <span class="excerpt">{p.data.excerpt}</span>}
|
||||
</li>
|
||||
))
|
||||
}
|
||||
</ul>
|
||||
{posts.length === 0 && <p id="empty">No posts</p>}
|
||||
</body>
|
||||
</html>
|
||||
21
e2e/fixture/src/pages/posts/[slug].astro
Normal file
21
e2e/fixture/src/pages/posts/[slug].astro
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
import { getEmDashEntry } from "emdash";
|
||||
import { PortableText, Comments, CommentForm } from "emdash/ui";
|
||||
|
||||
const { slug } = Astro.params;
|
||||
if (!slug) return Astro.redirect("/404");
|
||||
const { entry: post } = await getEmDashEntry("posts", slug);
|
||||
if (!post) return new Response("Not found", { status: 404 });
|
||||
---
|
||||
|
||||
<html>
|
||||
<body>
|
||||
<article>
|
||||
<h1 id="title">{post.data.title}</h1>
|
||||
{post.data.excerpt && <p id="excerpt">{post.data.excerpt}</p>}
|
||||
<div id="body"><PortableText value={post.data.body} /></div>
|
||||
</article>
|
||||
<Comments collection="posts" contentId={post.data.id} threaded />
|
||||
<CommentForm collection="posts" contentId={post.data.id} />
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user