mirror of
https://github.com/webstudio-is/webstudio.git
synced 2026-11-05 19:49:57 +09:00
## Description 1. What is this PR about (link the issue and add a short description) ## Steps for reproduction 1. click button 2. expect xyz ## Code Review - [ ] hi @kof, I need you to do - conceptual review (architecture, feature-correctness) - detailed review (read every line) - test it on preview ## Before requesting a review - [ ] made a self-review - [ ] added inline comments where things may be not obvious (the "why", not "what") ## Before merging - [ ] tested locally and on preview environment (preview dev login: 5de6) - [ ] updated [test cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md) document - [ ] added tests - [ ] if any new env variables are added, added them to `.env` file
405 lines
12 KiB
TypeScript
405 lines
12 KiB
TypeScript
import { describe, expect, test } from "@jest/globals";
|
|
import type { Project } from "@webstudio-is/project";
|
|
import {
|
|
ROOT_FOLDER_ID,
|
|
encodeDataSourceVariable,
|
|
type DataSource,
|
|
type Instance,
|
|
type WebstudioData,
|
|
} from "@webstudio-is/sdk";
|
|
import {
|
|
createDefaultPages,
|
|
createRootFolder,
|
|
} from "@webstudio-is/project-build";
|
|
import { $project } from "./nano-states";
|
|
import { insertPageCopyMutable } from "./page-utils";
|
|
|
|
const toMap = <T extends { id: string }>(list: T[]) =>
|
|
new Map(list.map((item) => [item.id, item]));
|
|
|
|
const getWebstudioDataStub = (
|
|
data?: Partial<WebstudioData>
|
|
): WebstudioData => ({
|
|
pages: createDefaultPages({ rootInstanceId: "", systemDataSourceId: "" }),
|
|
assets: new Map(),
|
|
dataSources: new Map(),
|
|
resources: new Map(),
|
|
instances: new Map(),
|
|
props: new Map(),
|
|
breakpoints: new Map(),
|
|
styleSourceSelections: new Map(),
|
|
styleSources: new Map(),
|
|
styles: new Map(),
|
|
...data,
|
|
});
|
|
|
|
describe("insert page copy", () => {
|
|
$project.set({ id: "projectId" } as Project);
|
|
|
|
test("insert home page copy with new path and ids", () => {
|
|
const data = getWebstudioDataStub({
|
|
instances: toMap<Instance>([
|
|
{ type: "instance", id: "bodyId", component: "Body", children: [] },
|
|
]),
|
|
dataSources: toMap<DataSource>([
|
|
{
|
|
id: "systemId",
|
|
scopeInstanceId: "bodyId",
|
|
name: "system",
|
|
type: "parameter",
|
|
},
|
|
]),
|
|
pages: {
|
|
meta: {},
|
|
homePage: {
|
|
id: "pageId",
|
|
name: "Name",
|
|
path: "",
|
|
title: `"Title"`,
|
|
meta: {},
|
|
rootInstanceId: "bodyId",
|
|
systemDataSourceId: "systemId",
|
|
},
|
|
pages: [],
|
|
folders: [createRootFolder(["pageId"])],
|
|
},
|
|
});
|
|
insertPageCopyMutable({
|
|
source: { data, pageId: "pageId" },
|
|
target: { data, folderId: ROOT_FOLDER_ID },
|
|
});
|
|
expect(data.pages.pages.length).toEqual(1);
|
|
const newPage = data.pages.pages[0];
|
|
expect(newPage).toEqual({
|
|
id: expect.not.stringMatching("pageId"),
|
|
name: "Name (1)",
|
|
path: "/copy-1",
|
|
title: `"Title"`,
|
|
meta: {},
|
|
rootInstanceId: expect.not.stringMatching("bodyId"),
|
|
systemDataSourceId: expect.not.stringMatching("systemId"),
|
|
});
|
|
expect(data.dataSources.size).toEqual(2);
|
|
expect(Array.from(data.dataSources.values())[1]).toEqual({
|
|
id: newPage.systemDataSourceId,
|
|
scopeInstanceId: newPage.rootInstanceId,
|
|
name: "system",
|
|
type: "parameter",
|
|
});
|
|
expect(data.instances.size).toEqual(2);
|
|
expect(Array.from(data.instances.values())[1]).toEqual({
|
|
type: "instance",
|
|
id: newPage.rootInstanceId,
|
|
component: "Body",
|
|
children: [],
|
|
});
|
|
});
|
|
|
|
test("deduplicate path for non-home page copy", () => {
|
|
const data = getWebstudioDataStub({
|
|
instances: toMap<Instance>([
|
|
{ type: "instance", id: "bodyId", component: "Body", children: [] },
|
|
]),
|
|
dataSources: toMap<DataSource>([
|
|
{
|
|
id: "systemId",
|
|
scopeInstanceId: "bodyId",
|
|
name: "system",
|
|
type: "parameter",
|
|
},
|
|
]),
|
|
pages: {
|
|
meta: {},
|
|
homePage: {
|
|
id: "homePageId",
|
|
name: "Home",
|
|
path: "",
|
|
title: `"Home"`,
|
|
meta: {},
|
|
rootInstanceId: "bodyId",
|
|
systemDataSourceId: "systemId",
|
|
},
|
|
pages: [
|
|
{
|
|
id: "pageId",
|
|
name: "Name",
|
|
path: "/my-path",
|
|
title: `"Title"`,
|
|
meta: {},
|
|
rootInstanceId: "bodyId",
|
|
systemDataSourceId: "systemId",
|
|
},
|
|
],
|
|
folders: [createRootFolder(["homePageId", "pageId"])],
|
|
},
|
|
});
|
|
insertPageCopyMutable({
|
|
source: { data, pageId: "pageId" },
|
|
target: { data, folderId: ROOT_FOLDER_ID },
|
|
});
|
|
expect(data.pages.pages.length).toEqual(2);
|
|
const newPage = data.pages.pages[1];
|
|
expect(newPage.path).toEqual("/copy-1/my-path");
|
|
});
|
|
|
|
test("deduplicate wildcards in page copy", () => {
|
|
const data = getWebstudioDataStub({
|
|
instances: toMap<Instance>([
|
|
{ type: "instance", id: "bodyId", component: "Body", children: [] },
|
|
]),
|
|
dataSources: toMap<DataSource>([
|
|
{
|
|
id: "systemId",
|
|
scopeInstanceId: "bodyId",
|
|
name: "system",
|
|
type: "parameter",
|
|
},
|
|
]),
|
|
pages: {
|
|
meta: {},
|
|
homePage: {
|
|
id: "homePageId",
|
|
name: "Home",
|
|
path: "",
|
|
title: `"Home"`,
|
|
meta: {},
|
|
rootInstanceId: "bodyId",
|
|
systemDataSourceId: "systemId",
|
|
},
|
|
pages: [
|
|
{
|
|
id: "page1Id",
|
|
name: "My Name 1",
|
|
// unnamed wildcard
|
|
path: "/my-path/*",
|
|
title: `"My Title"`,
|
|
meta: {},
|
|
rootInstanceId: "bodyId",
|
|
systemDataSourceId: "systemId",
|
|
},
|
|
{
|
|
id: "page2Id",
|
|
name: "My Name 2",
|
|
// Named wildcard
|
|
path: "/my-path/name*",
|
|
title: `"My Title"`,
|
|
meta: {},
|
|
rootInstanceId: "bodyId",
|
|
systemDataSourceId: "systemId",
|
|
},
|
|
],
|
|
folders: [createRootFolder(["homePageId", "page1Id", "page2Id"])],
|
|
},
|
|
});
|
|
insertPageCopyMutable({
|
|
source: { data, pageId: "page1Id" },
|
|
target: { data, folderId: ROOT_FOLDER_ID },
|
|
});
|
|
insertPageCopyMutable({
|
|
source: { data, pageId: "page2Id" },
|
|
target: { data, folderId: ROOT_FOLDER_ID },
|
|
});
|
|
expect(data.pages.pages.length).toEqual(4);
|
|
const newPage1 = data.pages.pages[2];
|
|
const newPage2 = data.pages.pages[3];
|
|
expect(newPage1.path).toEqual("/copy-1/my-path/*");
|
|
expect(newPage2.path).toEqual("/copy-1/my-path/name*");
|
|
});
|
|
|
|
test("check full page path when duplicate inside a folder", () => {
|
|
const data = getWebstudioDataStub({
|
|
instances: toMap<Instance>([
|
|
{ type: "instance", id: "bodyId", component: "Body", children: [] },
|
|
]),
|
|
dataSources: toMap<DataSource>([
|
|
{
|
|
id: "systemId",
|
|
scopeInstanceId: "bodyId",
|
|
name: "system",
|
|
type: "parameter",
|
|
},
|
|
]),
|
|
pages: {
|
|
meta: {},
|
|
homePage: {
|
|
id: "homePageId",
|
|
name: "Home",
|
|
path: "",
|
|
title: `"Home"`,
|
|
meta: {},
|
|
rootInstanceId: "bodyId",
|
|
systemDataSourceId: "systemId",
|
|
},
|
|
pages: [
|
|
{
|
|
id: "pageId",
|
|
name: "My Name",
|
|
path: "/my-path",
|
|
title: `"My Title"`,
|
|
meta: {},
|
|
rootInstanceId: "bodyId",
|
|
systemDataSourceId: "systemId",
|
|
},
|
|
],
|
|
folders: [
|
|
createRootFolder(["folderId"]),
|
|
{
|
|
id: "folderId",
|
|
name: "Folder",
|
|
slug: "folder",
|
|
children: ["pageId"],
|
|
},
|
|
],
|
|
},
|
|
});
|
|
insertPageCopyMutable({
|
|
source: { data, pageId: "pageId" },
|
|
target: { data, folderId: "folderId" },
|
|
});
|
|
insertPageCopyMutable({
|
|
source: { data, pageId: "pageId" },
|
|
target: { data, folderId: ROOT_FOLDER_ID },
|
|
});
|
|
expect(data.pages.pages.length).toEqual(3);
|
|
const nestedPage = data.pages.pages[1];
|
|
const rootPage = data.pages.pages[2];
|
|
expect(nestedPage.path).toEqual("/copy-1/my-path");
|
|
expect(rootPage.path).toEqual("/my-path");
|
|
});
|
|
|
|
test("replace variables in page copy meta", () => {
|
|
const data = getWebstudioDataStub({
|
|
instances: toMap<Instance>([
|
|
{ type: "instance", id: "bodyId", component: "Body", children: [] },
|
|
]),
|
|
dataSources: toMap<DataSource>([
|
|
{
|
|
id: "systemId",
|
|
scopeInstanceId: "bodyId",
|
|
name: "system",
|
|
type: "parameter",
|
|
},
|
|
]),
|
|
pages: {
|
|
meta: {},
|
|
homePage: {
|
|
id: "pageId",
|
|
name: "Name",
|
|
path: "",
|
|
title: `"Title: " + $ws$dataSource$systemId.params.value`,
|
|
meta: {
|
|
description: `"Description: " + $ws$dataSource$systemId.params.value`,
|
|
excludePageFromSearch: `"Exclude: " + $ws$dataSource$systemId.params.value`,
|
|
socialImageUrl: `"Image: " + $ws$dataSource$systemId.params.value`,
|
|
language: `"Language: " + $ws$dataSource$systemId.params.value`,
|
|
status: `"Status: " + $ws$dataSource$systemId.params.value`,
|
|
redirect: `"Redirect: " + $ws$dataSource$systemId.params.value`,
|
|
custom: [
|
|
{
|
|
property: "Property",
|
|
content: `"Value: " + $ws$dataSource$systemId.params.value`,
|
|
},
|
|
],
|
|
},
|
|
rootInstanceId: "bodyId",
|
|
systemDataSourceId: "systemId",
|
|
},
|
|
pages: [],
|
|
folders: [createRootFolder(["pageId"])],
|
|
},
|
|
});
|
|
insertPageCopyMutable({
|
|
source: { data, pageId: "pageId" },
|
|
target: { data, folderId: ROOT_FOLDER_ID },
|
|
});
|
|
expect(data.pages.pages.length).toEqual(1);
|
|
const newPage = data.pages.pages[0];
|
|
const newSystem = Array.from(data.dataSources.values())[1];
|
|
expect(newSystem.id).not.toEqual("systemId");
|
|
const newSystemName = encodeDataSourceVariable(newSystem.id);
|
|
expect(newPage).toEqual({
|
|
id: expect.not.stringMatching("pageId"),
|
|
name: "Name (1)",
|
|
path: "/copy-1",
|
|
title: `"Title: " + ${newSystemName}.params.value`,
|
|
meta: {
|
|
description: `"Description: " + ${newSystemName}.params.value`,
|
|
excludePageFromSearch: `"Exclude: " + ${newSystemName}.params.value`,
|
|
socialImageUrl: `"Image: " + ${newSystemName}.params.value`,
|
|
language: `"Language: " + ${newSystemName}.params.value`,
|
|
status: `"Status: " + ${newSystemName}.params.value`,
|
|
redirect: `"Redirect: " + ${newSystemName}.params.value`,
|
|
custom: [
|
|
{
|
|
property: "Property",
|
|
content: `"Value: " + ${newSystemName}.params.value`,
|
|
},
|
|
],
|
|
},
|
|
rootInstanceId: expect.not.stringMatching("bodyId"),
|
|
systemDataSourceId: expect.not.stringMatching("systemId"),
|
|
});
|
|
});
|
|
|
|
test("append number to name only when conflict is found", () => {
|
|
const data = getWebstudioDataStub({
|
|
instances: toMap<Instance>([
|
|
{ type: "instance", id: "bodyId", component: "Body", children: [] },
|
|
]),
|
|
dataSources: toMap<DataSource>([
|
|
{
|
|
id: "systemId",
|
|
scopeInstanceId: "bodyId",
|
|
name: "system",
|
|
type: "parameter",
|
|
},
|
|
]),
|
|
pages: {
|
|
meta: {},
|
|
homePage: {
|
|
id: "pageId",
|
|
name: "Name",
|
|
path: "",
|
|
title: `"Title"`,
|
|
meta: {},
|
|
rootInstanceId: "bodyId",
|
|
systemDataSourceId: "systemId",
|
|
},
|
|
pages: [],
|
|
folders: [
|
|
createRootFolder(["pageId", "folderId"]),
|
|
{
|
|
id: "folderId",
|
|
name: "Folder",
|
|
slug: "folder",
|
|
children: [],
|
|
},
|
|
],
|
|
},
|
|
});
|
|
insertPageCopyMutable({
|
|
source: { data, pageId: "pageId" },
|
|
target: { data, folderId: ROOT_FOLDER_ID },
|
|
});
|
|
insertPageCopyMutable({
|
|
source: { data, pageId: "pageId" },
|
|
target: { data, folderId: ROOT_FOLDER_ID },
|
|
});
|
|
insertPageCopyMutable({
|
|
source: { data, pageId: "pageId" },
|
|
target: { data, folderId: "folderId" },
|
|
});
|
|
insertPageCopyMutable({
|
|
source: { data, pageId: "pageId" },
|
|
target: { data, folderId: "folderId" },
|
|
});
|
|
expect(data.pages.pages.length).toEqual(4);
|
|
// inside folder with conflict
|
|
expect(data.pages.pages[0].name).toEqual(`Name (1)`);
|
|
expect(data.pages.pages[1].name).toEqual(`Name (2)`);
|
|
// inside folder without conflict
|
|
expect(data.pages.pages[2].name).toEqual(`Name`);
|
|
expect(data.pages.pages[3].name).toEqual(`Name (1)`);
|
|
});
|
|
});
|