Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
250 changes: 238 additions & 12 deletions lib/src/commands/pull.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { pull } from "./pull";
import httpClient from "../http/client";
import { TextItem } from "../http/textItems";
import { Component, TextItem } from "../http/types";
import appContext from "../utils/appContext";
import * as path from "path";
import * as fs from "fs";
Expand All @@ -24,6 +24,19 @@ const createMockTextItem = (overrides: Partial<TextItem> = {}) => ({
...overrides,
});

const createMockComponent = (overrides: Partial<Component> = {}) => ({
id: "component-1",
text: "Plain text content",
richText: "<p>Rich <strong>HTML</strong> content</p>",
status: "active",
notes: "",
tags: [],
variableIds: [],
folderId: null,
variantId: null,
...overrides,
})

const createMockVariable = (overrides: any = {}) => ({
id: "var-1",
name: "Variable 1",
Expand All @@ -36,14 +49,17 @@ const createMockVariable = (overrides: any = {}) => ({
});

// Helper functions
const setupMocks = (textItems: TextItem[] = [], variables: any[] = []) => {
const setupMocks = ({ textItems = [], components = [], variables = [] }: { textItems: TextItem[]; components?: Component[]; variables?: any[] }) => {
mockHttpClient.get.mockImplementation((url: string) => {
if (url.includes("/v2/textItems")) {
return Promise.resolve({ data: textItems });
}
if (url.includes("/v2/variables")) {
return Promise.resolve({ data: variables });
}
if (url.includes("/v2/components")) {
return Promise.resolve({ data: components });
}
return Promise.resolve({ data: [] });
});
};
Expand All @@ -55,11 +71,11 @@ const parseJsonFile = (filepath: string) => {

const assertFileContainsText = (
filepath: string,
textId: string,
devId: string,
expectedText: string
) => {
const content = parseJsonFile(filepath);
expect(content[textId]).toBe(expectedText);
expect(content[devId]).toBe(expectedText);
};

const assertFilesCreated = (outputDir: string, expectedFiles: string[]) => {
Expand Down Expand Up @@ -105,11 +121,13 @@ describe("pull command - end-to-end tests", () => {
fs.mkdirSync(outputDir, { recursive: true });

const mockTextItem = createMockTextItem();
setupMocks([mockTextItem], []);
const mockComponent = createMockComponent();
setupMocks({ textItems: [mockTextItem], components: [mockComponent]});

// Set up appContext - this is what actually drives the test
appContext.setProjectConfig({
projects: [{ id: "project-1" }],
components: {},
richText: "html",
outputs: [{ format: "json", outDir: outputDir }],
});
Expand All @@ -122,17 +140,25 @@ describe("pull command - end-to-end tests", () => {
"text-1",
"<p>Rich <strong>HTML</strong> content</p>"
);

assertFileContainsText(
path.join(outputDir, "components___base.json"),
"component-1",
"<p>Rich <strong>HTML</strong> content</p>"
)
});

it("should use plain text when richText is disabled at output level", async () => {
fs.mkdirSync(outputDir, { recursive: true });

const mockTextItem = createMockTextItem();
setupMocks([mockTextItem], []);
const mockComponent = createMockComponent();
setupMocks({ textItems: [mockTextItem], components: [mockComponent] });

appContext.setProjectConfig({
projects: [{ id: "project-1" }],
richText: "html",
components: {},
outputs: [{ format: "json", outDir: outputDir, richText: false }],
});

Expand All @@ -144,13 +170,19 @@ describe("pull command - end-to-end tests", () => {
"text-1",
"Plain text content"
);

assertFileContainsText(
path.join(outputDir, "components___base.json"),
"component-1",
"Plain text content"
);
});

it("should use rich text when enabled only at output level", async () => {
fs.mkdirSync(outputDir, { recursive: true });

const mockTextItem = createMockTextItem();
setupMocks([mockTextItem], []);
setupMocks({ textItems: [mockTextItem] });

appContext.setProjectConfig({
projects: [{ id: "project-1" }],
Expand Down Expand Up @@ -217,6 +249,137 @@ describe("pull command - end-to-end tests", () => {
});
});

it("should query components when source field is provided", async () => {
fs.mkdirSync(outputDir, { recursive: true });

appContext.setProjectConfig({
components: {},
outputs: [
{
format: "json",
outDir: outputDir,
},
],
});

await pull();

expect(mockHttpClient.get).toHaveBeenCalledWith("/v2/components", {
params: {
filter:
'{}',
},
});
})

it("should filter components by folder at base level", async () => {
fs.mkdirSync(outputDir, { recursive: true });

appContext.setProjectConfig({
components: {
folders: [{ id: "folder-1" }],
},
outputs: [
{
format: "json",
outDir: outputDir,
},
],
});

await pull();

expect(mockHttpClient.get).toHaveBeenCalledWith("/v2/components", {
params: {
filter:
'{"folders":[{"id":"folder-1"}]}',
},
});
})

it("should filter components by folder and variants at base level", async () => {
fs.mkdirSync(outputDir, { recursive: true });

appContext.setProjectConfig({
components: {
folders: [{ id: "folder-1" }],
},
variants: [{ id: "variant-a" }, { id: "variant-b" }],
outputs: [
{
format: "json",
outDir: outputDir,
},
],
});

await pull();

expect(mockHttpClient.get).toHaveBeenCalledWith("/v2/components", {
params: {
filter:
'{"folders":[{"id":"folder-1"}],"variants":[{"id":"variant-a"},{"id":"variant-b"}]}',
},
});
})

it("should filter components by folder at output level", async () => {
fs.mkdirSync(outputDir, { recursive: true });

appContext.setProjectConfig({
components: {
folders: [{ id: "folder-1" }],
},
outputs: [
{
format: "json",
outDir: outputDir,
components: {
folders: [{ id: "folder-3" }]
}
},
],
});

await pull();

expect(mockHttpClient.get).toHaveBeenCalledWith("/v2/components", {
params: {
filter:
'{"folders":[{"id":"folder-3"}]}',
},
});
})

it("should filter components by folder and variants at output level", async () => {
fs.mkdirSync(outputDir, { recursive: true });

appContext.setProjectConfig({
components: {
folders: [{ id: "folder-1" }],
},
outputs: [
{
format: "json",
outDir: outputDir,
components: {
folders: [{ id: "folder-3" }]
},
variants: [{ id: "variant-a" }, { id: "variant-b" }],
},
],
});

await pull();

expect(mockHttpClient.get).toHaveBeenCalledWith("/v2/components", {
params: {
filter:
'{"folders":[{"id":"folder-3"}],"variants":[{"id":"variant-a"},{"id":"variant-b"}]}',
},
});
})

it("should filter projects at output level", async () => {
fs.mkdirSync(outputDir, { recursive: true });

Expand Down Expand Up @@ -271,6 +434,7 @@ describe("pull command - end-to-end tests", () => {
fs.mkdirSync(outputDir, { recursive: true });

appContext.setProjectConfig({
projects: [],
outputs: [
{
format: "json",
Expand All @@ -284,16 +448,31 @@ describe("pull command - end-to-end tests", () => {
// Verify correct API call with filtered params
expect(mockHttpClient.get).toHaveBeenCalledWith("/v2/textItems", {
params: {
filter: "{}",
filter: "{\"projects\":[]}",
},
});
expect(mockHttpClient.get).toHaveBeenCalledWith("/v2/variables")

// Components endpoint should not be called if not provided as source field
expect(mockHttpClient.get).toHaveBeenCalledTimes(2)
});
});

describe("Output files", () => {
it("should create output files for each project and variant returned from the API", async () => {
fs.mkdirSync(outputDir, { recursive: true });

appContext.setProjectConfig({
projects: [],
components: {},
outputs: [
{
format: "json",
outDir: outputDir,
},
],
});

// project-1 and project-2 each have at least one base text item
const baseTextItems = [
createMockTextItem({
Expand Down Expand Up @@ -341,10 +520,54 @@ describe("pull command - end-to-end tests", () => {
}),
];

setupMocks(
[...baseTextItems, ...variantATextItems, ...variantBTextItems],
[]
);
const componentsBase = [
createMockComponent({
id: "comp-1",
variantId: null,
folderId: null,
}),
createMockComponent({
id: "comp-2",
variantId: null,
folderId: "folder-1",
}),
createMockComponent({
id: "comp-3",
variantId: null,
folderId: "folder-2",
}),
]

const componentsVariantA = [
createMockComponent({
id: "comp-4",
variantId: "variant-a",
folderId: null,
}),
createMockComponent({
id: "comp-5",
variantId: "variant-a",
folderId: "folder-1",
}),
]

const componentsVariantB = [
createMockComponent({
id: "comp-6",
variantId: "variant-b",
folderId: null,
}),
createMockComponent({
id: "comp-7",
variantId: "variant-b",
folderId: "folder-1",
}),
]

setupMocks({
textItems: [...baseTextItems, ...variantATextItems, ...variantBTextItems],
components: [...componentsBase, ...componentsVariantA, ...componentsVariantB],
});

await pull();

Expand All @@ -355,6 +578,9 @@ describe("pull command - end-to-end tests", () => {
"project-1___variant-b.json",
"project-2___base.json",
"project-2___variant-a.json",
"components___base.json",
"components___variant-a.json",
"components___variant-b.json",
"variables.json",
]);
});
Expand Down
Loading