Skip to content

Commit

Permalink
fix(page type): Convert to page type should create slice zone for mai…
Browse files Browse the repository at this point in the history
…n tab if necessary
  • Loading branch information
xrutayisire committed Oct 16, 2023
1 parent eada429 commit 725e9ab
Show file tree
Hide file tree
Showing 3 changed files with 287 additions and 5 deletions.
93 changes: 93 additions & 0 deletions packages/slice-machine/src/domain/CustomTypeModel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import {
CustomType,
DynamicSection,
DynamicSlicesConfig,
} from "@prismicio/types-internal/lib/customtypes";

export const CustomTypeModel = {
getSectionsEntries(customType: CustomType): [string, DynamicSection][] {
return Object.entries(customType.json);
},

getMainSectionEntry(
customType: CustomType
): [string, DynamicSection] | undefined {
// Currently we cannot rely on the name of the main section
// since it's possible to rename it
const sections = CustomTypeModel.getSectionsEntries(customType);
return sections.length > 0 ? sections[0] : undefined;
},

getSection(
customType: CustomType,
sectionId: string
): DynamicSection | undefined {
return customType.json[sectionId];
},

getSectionSliceZoneConfig(
customType: CustomType,
sectionId: string
): DynamicSlicesConfig | undefined {
const section = CustomTypeModel.getSection(customType, sectionId);

if (section === undefined) {
return undefined;
}

const maybeSliceZone = Object.entries(section).find(
([, value]) => value.type === "Slices"
);

return maybeSliceZone ? maybeSliceZone[1]?.config : undefined;
},

createSectionSliceZone(
customType: CustomType,
sectionId: string
): CustomType {
const maybeSectionSliceZoneConfig =
CustomTypeModel.getSectionSliceZoneConfig(customType, sectionId);

// If the section already has a slice zone, return the custom type as is
if (maybeSectionSliceZoneConfig) {
return customType;
}

return {
...customType,
json: {
...customType.json,
[sectionId]: {
...customType.json[sectionId],
slices: {
type: "Slices",
fieldset: "Slice Zone",
config: {
choices: {},
},
},
},
},
};
},

convertToPageType(customType: CustomType): CustomType {
const mainSectionEntry = CustomTypeModel.getMainSectionEntry(customType);
let newCustomType: CustomType = {
...customType,
format: "page",
};

// Create the slice zone for the main section if it doesn't exist
if (mainSectionEntry) {
const [mainSectionKey] = mainSectionEntry;
newCustomType = CustomTypeModel.createSectionSliceZone(
newCustomType,
mainSectionKey
);
}

return newCustomType;
},
};
190 changes: 190 additions & 0 deletions packages/slice-machine/src/domain/__tests__/CustomTypeModel.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
import { describe, expect } from "vitest";

import {
CustomType,
DynamicSection,
} from "@prismicio/types-internal/lib/customtypes";

import { CustomTypeModel } from "../CustomTypeModel";

describe("CustomTypeModel test suite", () => {
const MainSection: DynamicSection = {
uid: {
config: {
label: "MainSectionField",
},
type: "UID",
},
slices: {
type: "Slices",
fieldset: "Slice Zone",
config: {
choices: {
hero_banner: {
type: "SharedSlice",
},
promo_section_image_tiles: {
type: "SharedSlice",
},
},
},
},
};
const AnotherSection: DynamicSection = {
uid: {
config: {
label: "AnotherSectionField",
},
type: "UID",
},
};
const mockCustomType: CustomType = {
format: "custom",
id: "id",
json: {
MainSection,
AnotherSection,
},
label: "lama",
repeatable: true,
status: true,
};

it("getSectionsEntries should return the sections entries", () => {
expect(CustomTypeModel.getSectionsEntries(mockCustomType)).toEqual([
["MainSection", MainSection],
["AnotherSection", AnotherSection],
]);
});

it("getSections should return an empty array if there are no sections", () => {
expect(
CustomTypeModel.getSectionsEntries({
...mockCustomType,
json: {},
})
).toEqual([]);
});

it("getMainSectionEntry should return the first section even if not named Main", () => {
expect(CustomTypeModel.getMainSectionEntry(mockCustomType)).toEqual([
"MainSection",
MainSection,
]);
});

it("getMainSectionEntry should return undefined if there is are sections", () => {
expect(
CustomTypeModel.getMainSectionEntry({
...mockCustomType,
json: {},
})
).toEqual(undefined);
});

it("getSection should return the section matching the key", () => {
expect(
CustomTypeModel.getSection(mockCustomType, "AnotherSection")
).toEqual(AnotherSection);
});

it("getSection should return undefined if there are no sections", () => {
expect(
CustomTypeModel.getSection(
{
...mockCustomType,
json: {},
},
"MainSection"
)
).toEqual(undefined);
});

it("getSectionSliceZoneConfig should return the config of the given section", () => {
expect(
CustomTypeModel.getSectionSliceZoneConfig(mockCustomType, "MainSection")
).toEqual({
choices: {
hero_banner: {
type: "SharedSlice",
},
promo_section_image_tiles: {
type: "SharedSlice",
},
},
});
});

it("getSectionSliceZoneConfig should return undefined if there are no sections", () => {
expect(
CustomTypeModel.getSectionSliceZoneConfig(
{
...mockCustomType,
json: {},
},
"MainSection"
)
).toEqual(undefined);
});

it("createSectionSliceZone should return the given custom type with a slice zone for given section", () => {
expect(
CustomTypeModel.createSectionSliceZone(mockCustomType, "AnotherSection")
).toEqual({
...mockCustomType,
json: {
...mockCustomType.json,
AnotherSection: {
...mockCustomType.json.AnotherSection,
slices: {
type: "Slices",
fieldset: "Slice Zone",
config: {
choices: {},
},
},
},
},
});
});

it("createSectionSliceZone should return the same custom type if slice zone already exist for given section", () => {
expect(
CustomTypeModel.createSectionSliceZone(mockCustomType, "MainSection")
).toEqual(mockCustomType);
});

it("convertToPageType should convert the given custom type", () => {
expect(CustomTypeModel.convertToPageType(mockCustomType)).toEqual({
...mockCustomType,
format: "page",
});
});

it("convertToPageType should convert the given custom type with a slice zone for Main section when it doesn't exist", () => {
expect(
CustomTypeModel.convertToPageType({
...mockCustomType,
json: {
MainSection: {},
AnotherSection,
},
})
).toEqual({
...mockCustomType,
json: {
MainSection: {
slices: {
type: "Slices",
fieldset: "Slice Zone",
config: {
choices: {},
},
},
},
AnotherSection,
},
format: "page",
});
});
});
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { toast } from "react-toastify";

import { CustomType } from "@prismicio/types-internal/lib/customtypes";

import { CustomTypeFormat } from "@slicemachine/manager";
import { CustomTypeModel } from "@src/domain/CustomTypeModel";
import { managerClient } from "@src/managerClient";

import { CUSTOM_TYPES_MESSAGES } from "../customTypesMessages";

export async function convertCustomToPageType(
Expand All @@ -13,10 +15,7 @@ export async function convertCustomToPageType(
CUSTOM_TYPES_MESSAGES[customType.format as CustomTypeFormat];

try {
const newCustomType: CustomType = {
...customType,
format: "page",
};
const newCustomType = CustomTypeModel.convertToPageType(customType);
await managerClient.customTypes.updateCustomType({
model: newCustomType,
});
Expand Down

0 comments on commit 725e9ab

Please sign in to comment.