@embeddable.com/sdk-core
Version:
Core Embeddable SDK module responsible for web-components bundling and publishing.
215 lines (183 loc) • 7.25 kB
text/typescript
import { describe, it, expect, vi, beforeEach, afterEach, Mock } from "vitest";
import * as http from "node:http";
import axios from "axios";
import provideConfig from "./provideConfig";
import buildGlobalHooks from "./buildGlobalHooks";
import { getToken } from "./login";
import * as chokidar from "chokidar";
import dev from "./dev";
import { checkNodeVersion } from "./utils";
import { createManifest } from "./cleanup";
import prepare from "./prepare";
import { WebSocketServer } from "ws";
import * as open from "open";
import { logError } from "./logger";
import { ResolvedEmbeddableConfig } from "./defineConfig";
import { RollupWatcher } from "rollup";
import build from "./build";
// Mock dependencies
vi.mock("./buildTypes", () => ({ default: vi.fn() }));
vi.mock("./buildGlobalHooks", () => ({ default: vi.fn() }));
vi.mock("./prepare", () => ({ default: vi.fn(), removeIfExists: vi.fn() }));
vi.mock("./generate", () => ({ default: vi.fn() }));
vi.mock("./provideConfig", () => ({ default: vi.fn() }));
vi.mock("@stencil/core/sys/node", () => ({
createNodeLogger: vi.fn(),
createNodeSys: vi.fn(),
}));
vi.mock("open", () => ({ default: vi.fn() }));
vi.mock("ws", () => ({ WebSocketServer: vi.fn() }));
vi.mock("chokidar", () => ({ watch: vi.fn((_) => ({ on: vi.fn() })) }));
vi.mock("./login", () => ({ getToken: vi.fn(), default: vi.fn() }));
vi.mock("axios", () => ({ default: { get: vi.fn(), post: vi.fn() } }));
vi.mock("@embeddable.com/sdk-utils", () => ({ findFiles: vi.fn() }));
vi.mock("./push", () => ({ archive: vi.fn(), sendBuild: vi.fn() }));
vi.mock("./validate", () => ({ default: vi.fn() }));
vi.mock("./utils", () => ({ checkNodeVersion: vi.fn() }));
vi.mock("./cleanup", () => ({ createManifest: vi.fn() }));
vi.mock("node:http", () => ({
createServer: vi.fn(() => ({ listen: vi.fn() })),
}));
vi.mock("./logger", () => ({
initLogger: vi.fn(),
logError: vi.fn(),
}));
const mockConfig = {
client: {
rootDir: "/mock/root",
buildDir: "/mock/root/.embeddable-dev-build",
componentDir: "/mock/root/.embeddable-dev-build/component",
stencilBuild: "/mock/root/.embeddable-dev-build/dist/embeddable-wrapper",
tmpDir: "/mock/root/.embeddable-dev-tmp",
globalCss: "/mock/root/global.css",
modelsSrc: "/mock/root/models",
presetsSrc: "/mock/root/presets",
componentLibraries: [],
},
plugins: [],
previewBaseUrl: "http://preview.example.com",
pushBaseUrl: "http://push.example.com",
};
describe("dev command", () => {
let listenMock: Mock;
beforeEach(() => {
listenMock = vi.fn();
vi.mocked(http.createServer).mockImplementation(
() =>
({
listen: listenMock,
}) as any
);
vi.mocked(WebSocketServer).mockImplementation(() => {
return {
clients: [],
on: vi.fn(),
} as any;
});
// Mock process.on to avoid actually setting up process listeners
vi.spyOn(process, "on").mockImplementation(() => process);
vi.spyOn(process, "exit").mockImplementation(() => undefined as never);
vi.mocked(provideConfig).mockResolvedValue(
mockConfig as unknown as ResolvedEmbeddableConfig
);
vi.mocked(getToken).mockResolvedValue("mock-token");
vi.mocked(axios.get).mockResolvedValue({
data: [{ workspaceId: "mock-workspace" }],
});
vi.mocked(axios.post).mockResolvedValue({
data: "mock-workspace",
});
// @ts-ignore
const watcherMock: RollupWatcher = { on: vi.fn(), close: vi.fn() };
vi.mocked(buildGlobalHooks).mockResolvedValue({
themeWatcher: watcherMock,
lifecycleWatcher: watcherMock,
});
});
afterEach(() => {
vi.restoreAllMocks();
});
it("should set up the development and open workspace page with pushComponents false", async () => {
vi.mocked(provideConfig).mockResolvedValue({
...mockConfig,
pushComponents: false,
pushModels: true,
} as unknown as ResolvedEmbeddableConfig);
// Run the dev command
await dev();
// Verify that the necessary functions were called
expect(checkNodeVersion).toHaveBeenCalled();
expect(prepare).toHaveBeenCalled();
expect(http.createServer).toHaveBeenCalled();
expect(WebSocketServer).toHaveBeenCalled();
// Verify that the server was set up to listen on the correct port
expect(listenMock).toHaveBeenCalledWith(8926, expect.any(Function));
// Call the listen callback to simulate the server being set up
listenMock.mock.calls[0][1]();
expect(createManifest).toHaveBeenCalled();
await expect.poll(() => chokidar.watch).toBeCalledTimes(1);
expect(open.default).toHaveBeenCalledWith(
"http://preview.example.com/workspace/mock-workspace"
);
});
it("should set up the development with pushComponents false", async () => {
vi.mocked(provideConfig).mockResolvedValue({
...mockConfig,
pushComponents: false,
pushModels: true,
} as unknown as ResolvedEmbeddableConfig);
// Run the dev command
await dev();
// Verify that the necessary functions were called
expect(checkNodeVersion).toHaveBeenCalled();
expect(prepare).toHaveBeenCalled();
expect(http.createServer).toHaveBeenCalled();
expect(WebSocketServer).toHaveBeenCalled();
// Verify that the server was set up to listen on the correct port
expect(listenMock).toHaveBeenCalledWith(8926, expect.any(Function));
// Call the listen callback to simulate the server being set up
listenMock.mock.calls[0][1]();
expect(createManifest).toHaveBeenCalled();
await expect.poll(() => chokidar.watch).toBeCalledTimes(1);
});
it("should set up the development environment with pushComponents true", async () => {
vi.mocked(provideConfig).mockResolvedValue({
...mockConfig,
pushComponents: true,
pushModels: true,
} as unknown as ResolvedEmbeddableConfig);
// Run the dev command
await dev();
// Verify that the necessary functions were called
expect(checkNodeVersion).toHaveBeenCalled();
expect(prepare).toHaveBeenCalled();
expect(http.createServer).toHaveBeenCalled();
expect(WebSocketServer).toHaveBeenCalled();
// Verify that the server was set up to listen on the correct port
expect(listenMock).toHaveBeenCalledWith(8926, expect.any(Function));
// Call the listen callback to simulate the server being set up
listenMock.mock.calls[0][1]();
expect(createManifest).toHaveBeenCalled();
await expect.poll(() => chokidar.watch).toBeCalledTimes(2);
});
it("should log errors and exit on failure", async () => {
const originalConsoleLog = console.log;
console.log = vi.fn();
const error = new Error("Test error");
const exitSpy = vi.spyOn(process, "exit").mockImplementation(() => {
throw new Error("process.exit");
});
vi.mocked(checkNodeVersion).mockImplementation(() => {
throw error;
});
await expect(dev()).rejects.toThrow("process.exit");
expect(console.log).toHaveBeenCalledWith(error);
expect(logError).toHaveBeenCalledWith({
command: "dev",
breadcrumbs: ["run dev"],
error,
});
expect(exitSpy).toHaveBeenCalledWith(1);
console.log = originalConsoleLog;
});
});