Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(c8yscrn): Fix setting of screenshot target folder overwrite #165

Merged
merged 1 commit into from
Oct 29, 2024
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
1 change: 1 addition & 0 deletions src/lib/screenshots/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@ export interface C8yScreenshotOptions {
quiet: boolean;
setup: ScreenshotSetup;
init: boolean;
clear: boolean;
}

export type C8yScreenshotActionHandler = (
Expand Down
53 changes: 52 additions & 1 deletion src/plugin/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
/// <reference types="jest" />

import { C8yPactDefaultFileAdapter, configureC8yPlugin } from "./index";
import {
appendCountIfPathExists,
C8yPactDefaultFileAdapter,
configureC8yPlugin,
} from "./index";
import path from "path";
import { vol } from "memfs";

jest.spyOn(process, "cwd").mockReturnValue("/home/user/test");
// eslint-disable-next-line @typescript-eslint/no-var-requires
jest.mock("fs", () => require("memfs").fs);

describe("plugin", () => {
describe("configurePlugin ", () => {
Expand Down Expand Up @@ -61,4 +68,48 @@ describe("plugin", () => {
expect((config.env as any).C8Y_PLUGIN_LOADED).toBe("true");
});
});

describe("appendCountIfPathExists", () => {
beforeEach(() => {
vol.fromNestedJSON({
"/home/user/test/cypress/screenshots": {
"my-screenshot-05.png": Buffer.from([8, 6, 7, 5, 3, 0, 9]),
"my-screenshot-04.png": Buffer.from([8, 6, 7, 5, 3, 0, 9]),
"my-screenshot-04 (2).png": Buffer.from([8, 6, 7, 5, 3, 0, 9]),
"my-screenshot-04 (3).png": Buffer.from([8, 6, 7, 5, 3, 0, 9]),
},
});
});

afterEach(() => {
vol.reset();
});

it("should append count if path exists", () => {
const result = appendCountIfPathExists(
"/home/user/test/cypress/screenshots/my-screenshot-05.png"
);
expect(result).toBe(
"/home/user/test/cypress/screenshots/my-screenshot-05 (2).png"
);
});

it("should not append count if path does not exists", () => {
const result = appendCountIfPathExists(
"/home/user/test/cypress/screenshots/my-screenshot-01.png"
);
expect(result).toBe(
"/home/user/test/cypress/screenshots/my-screenshot-01.png"
);
});

it("should increase count", () => {
const result = appendCountIfPathExists(
"/home/user/test/cypress/screenshots/my-screenshot-04.png"
);
expect(result).toBe(
"/home/user/test/cypress/screenshots/my-screenshot-04 (4).png"
);
});
});
});
43 changes: 33 additions & 10 deletions src/plugin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export function configureC8yPlugin(
config: Cypress.PluginConfigOptions,
options: C8yPluginConfig = {}
) {
const log = debug("c8y:c8yscrn:plugin");
const log = debug("c8y:plugin");

let adapter = options.pactAdapter;
if (!adapter) {
Expand Down Expand Up @@ -122,7 +122,7 @@ export function configureC8yPlugin(
"c8ypact:save": savePact,
"c8ypact:get": getPact,
"c8ypact:remove": removePact,
"c8ypact:oauthLogin": login,
"c8ypact:oauthLogin": login
});
}
}
Expand All @@ -141,9 +141,9 @@ export function configureC8yScreenshotPlugin(
) {
const log = debug("c8y:scrn:plugin");
let configData: string | ScreenshotSetup | undefined = setup;
if (config.env._c8yscrnyaml != null) {
log(`Using config from _c8yscrnyaml`);
configData = config.env._c8yscrnyaml;
if (config.env._c8yscrnConfigYaml != null) {
log(`Using config from _c8yscrnConfigYaml`);
configData = config.env._c8yscrnConfigYaml;
}

let lookupPaths: string[] = [];
Expand Down Expand Up @@ -186,6 +186,9 @@ export function configureC8yScreenshotPlugin(
);
}

const ajv = new C8yAjvSchemaMatcher();
ajv.match(configData, schema, true);

if (configData.global?.timeouts?.default) {
config.defaultCommandTimeout = configData.global.timeouts.default;
log(`Setting default command timeout to ${config.defaultCommandTimeout}`);
Expand All @@ -199,17 +202,20 @@ export function configureC8yScreenshotPlugin(
log(`Setting screenshot timeout to ${config.responseTimeout}`);
}

const ajv = new C8yAjvSchemaMatcher();
ajv.match(configData, schema, true);
log(
`Config validated. ${configData.screenshots?.length} screenshots configured.`
);

config.env._c8yscrnyaml = configData;
const overwrite = configData.global?.overwrite ?? false;

config.env._c8yscrnConfigYaml = configData;
config.baseUrl =
config.baseUrl ?? configData?.baseUrl ?? "http://localhost:8080";
log(`Using baseUrl ${config.baseUrl}`);

const screenshotsFolder = config.env._c8yscrnBrowserLaunchArgs ?? "c8yscrn";
log(`Using screenshotsFolder to ${screenshotsFolder}`);

// https://www.cypress.io/blog/generate-high-resolution-videos-and-screenshots
// https://github.com/cypress-io/cypress/issues/27260
on("before:browser:launch", (browser, launchOptions) => {
Expand Down Expand Up @@ -271,8 +277,12 @@ export function configureC8yScreenshotPlugin(
dimensions: details.dimensions,
});
}
log(`Moving screenshot ${details.path} to ${newPath}`);
fs.rename(details.path, newPath, (err) => {

// for Module API run(), overwrite option of the screenshot is not working
const targetPath = overwrite === true ? newPath : appendCountIfPathExists(newPath);
log(`Moving screenshot ${details.path} to ${targetPath} (overwrite: ${overwrite})`);

fs.rename(details.path, targetPath, (err) => {
if (err) return reject(err);
resolve({
path: newPath,
Expand All @@ -286,6 +296,19 @@ export function configureC8yScreenshotPlugin(
return config;
}

export function appendCountIfPathExists(newPath: string): string {
let count = 2;
let adjustedPath = newPath;

while (fs.existsSync(adjustedPath)) {
const parsedPath = path.parse(newPath);
adjustedPath = path.join(parsedPath.dir, `${parsedPath.name} (${count})${parsedPath.ext}`);
count++;
}

return adjustedPath;
}

function getVersion() {
try {
let currentDir = __dirname;
Expand Down
12 changes: 10 additions & 2 deletions src/screenshot/config.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
import { defineConfig } from "cypress";
import { configureC8yScreenshotPlugin } from "../plugin";

import debug from "debug";
const log = debug("c8y:scrn:cypress");

export default defineConfig({
e2e: {
baseUrl: "http://localhost:4200",
supportFile: false,
video: false,
videosFolder: "videos",
screenshotsFolder: "screenshots",
setupNodeEvents(on, config) {
configureC8yScreenshotPlugin(on, config);
on("task", {
"debug": (message: string) => {
log(message);
return null;
}
});

return config;
},
},
Expand Down
120 changes: 119 additions & 1 deletion src/screenshot/helper.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
import * as yaml from "yaml";

import { C8yAjvSchemaMatcher } from "../contrib/ajv";
import { createInitConfig } from "./helper";
import {
createInitConfig,
resolveConfigOptions,
resolveScreenshotFolder,
} from "./helper";
import schema from "./../screenshot/schema.json";

jest.spyOn(process, "cwd").mockReturnValue("/home/user/test");
Expand All @@ -20,4 +24,118 @@ describe("startup", () => {
}).not.toThrow();
});
});

describe("resolveScreenshotFolder", () => {
it("should throw error for current working directory", () => {
expect(() => {
resolveScreenshotFolder({
folder: ".",
});
}).toThrow(
`Please provide a screenshot folder path that does not resolve to the current working directory.`
);
});

it("should throw error for current working directory with absolute path", () => {
expect(() => {
resolveScreenshotFolder({
// use trailing slash
folder: "/home/user/test/",
});
}).toThrow(
`Please provide a screenshot folder path that does not resolve to the current working directory.`
);
});

it("should throw error for current working directory with path operations", () => {
expect(() => {
resolveScreenshotFolder({
// use trailing slash
folder: "/home/../home/user/test/",
});
}).toThrow(
`Please provide a screenshot folder path that does not resolve to the current working directory.`
);
});

it("should return folder for current working directory", () => {
expect(resolveScreenshotFolder({ folder: "c8yscrn" })).toBe(
"/home/user/test/c8yscrn"
);
});

it("should return absolute folder", () => {
expect(
resolveScreenshotFolder({ folder: "/my/path/to/c8yscrn/folder" })
).toBe("/my/path/to/c8yscrn/folder");
});

it("should return folder for folder hierarchy", () => {
expect(resolveScreenshotFolder({ folder: "my/c8yscrn/folder" })).toBe(
"/home/user/test/my/c8yscrn/folder"
);
});
});

describe("resolveConfigOptions", () => {
it("should return default options", () => {
const options = resolveConfigOptions({});
expect(options.browser).toBe("chrome");
expect(options.quiet).toBe(true);
expect(options.testingType).toBe("e2e");
expect(options.config.e2e.baseUrl).toBe("http://localhost:8080");
expect(options.config.e2e.screenshotsFolder).toBe(
"/home/user/test/c8yscrn"
);
expect(options.config.e2e.trashAssetsBeforeRuns).toBe(false);
expect(options.config.e2e.specPattern.endsWith(".ts")).toBe(true);
expect(options.configFile.endsWith(".ts")).toBe(true);
});

it("should return custom options", () => {
const options = resolveConfigOptions({
browser: "firefox",
clear: true,
folder: "my/c8yscrn/folder",
tags: ["tag1", "tag2"],
baseUrl: "http://localhost:4200",
});
expect(options.browser).toBe("firefox");
expect(options.quiet).toBe(true);
expect(options.testingType).toBe("e2e");
expect(options.config.e2e.baseUrl).toBe("http://localhost:4200");
expect(options.config.e2e.screenshotsFolder).toBe(
"/home/user/test/my/c8yscrn/folder"
);
expect(options.config.e2e.trashAssetsBeforeRuns).toBe(true);
expect(options.config.e2e.specPattern.endsWith(".ts")).toBe(true);
expect(options.configFile.endsWith(".ts")).toBe(true);
});
});

describe("resolveBaseUrl", () => {
const originalEnv = process.env;
beforeAll(() => {
process.env = {
...originalEnv,
C8Y_BASEURL: "http://localhost:4200",
};
});
afterAll(() => {
process.env = originalEnv;
});

it("should return custom base url", () => {
expect(
resolveConfigOptions({ baseUrl: "http://localhost:4200" }).config.e2e
.baseUrl
).toBe("http://localhost:4200");
});

it("should return base url from env", () => {
expect(resolveConfigOptions({}).config.e2e.baseUrl).toBe(
"http://localhost:4200"
);
});
});
});
Loading
Loading