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

feat(allure-cypress): impose some limits on step parameter values created from Cypress command arguments #1127

Merged
merged 10 commits into from
Sep 6, 2024
Merged
69 changes: 61 additions & 8 deletions packages/allure-cypress/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,30 @@ Learn more about Allure Cypress from the official documentation at


## Allure Cypress options
| Option | Description | Default |
|-----------------|----------------------------------------------------------------------------------------------------------------------|--------------------|
| resultsDir | The path of the results folder. | `./allure-results` |
| videoOnFailOnly | When video capturing is enabled, set this option to `true` to attach the video to failed specs only. | `undefined` |
| links | Allure Runtime API link templates. | `undefined` |
| environmentInfo | A set of key-value pairs to display in the Environment section of the report | `undefined` |
| categories | An array of category definitions, each describing a [category of defects](https://allurereport.org/docs/categories/) | `undefined` |

Customize Allure Cypress by providing a configuration object as the third argument
of `allureCypress`.

The following options are supported:

| Option | Description | Default |
|-------------------|----------------------------------------------------------------------------------------------------------------------|---------------------------------|
| resultsDir | The path of the results folder. | `./allure-results` |
| videoOnFailOnly | When video capturing is enabled, set this option to `true` to attach the video to failed specs only. | `false` |
| links | Allure Runtime API link templates. | `undefined` |
| stepsFromCommands | Options that affect how Allure creates steps from Cypress commands | See [below](#stepsfromcommands) |
| environmentInfo | A set of key-value pairs to display in the Environment section of the report | `undefined` |
| categories | An array of category definitions, each describing a [category of defects](https://allurereport.org/docs/categories/) | `undefined` |

### stepsFromCommands

| Property | Description | Default |
|-------------------|---------------------------------------------------------------------------------------------------------------------------------------------|---------|
| maxArgumentLength | The maximum length of the parameter value created from Cypress command argument. The rest of the characters are replaces with `...`. | 128 |
| maxArgumentDepth | The maximum depth of the Cypress command argument (an array or an object) that will be converted to the corresponding step parameter value. | 3 |


### Example

Here is an example of the Allure Cypress configuration:

Expand All @@ -100,6 +117,10 @@ export default defineConfig({
nameTemplate: "ISSUE-%s",
},
},
stepsFromCommands: {
maxArgumentLength: 64,
maxArgumentDepth: 5,
},
environmentInfo: {
OS: os.platform(),
Architecture: os.arch(),
Expand Down Expand Up @@ -157,7 +178,39 @@ export default defineConfig({
});
```

## Known limitations
## Common issues

### The test plan feature doesn't work

Make sure you pass the Cypress config as the second argument of `allureCypress`.

Correct:

```javascript
allureCypress(on, config);
```

Also correct:

```javascript
allureCypress(on, config, {
resultsDir: "output",
});
```

Incorrect (the test plan won't work):

```javascript
allureCypress(on);
```

Also incorrect (the legacy style; the test plan won't work either):

```javascript
allureCypress(on, {
resultsDir: "output",
});
```

### `setupNodeEvents` limitations

Expand Down
7 changes: 7 additions & 0 deletions packages/allure-cypress/src/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const ALLURE_REPORT_STEP_COMMAND = "__allure_report_step_command__";

export type AllureCypressConfig = ReporterConfig & {
videoOnFailOnly?: boolean;
stepsFromCommands?: Partial<AllureSpecState["config"]["stepsFromCommands"]>;
};

export type CypressSuite = Mocha.Suite & {
Expand Down Expand Up @@ -174,6 +175,12 @@ export type SpecContext = {
};

export type AllureSpecState = {
config: {
delatrie marked this conversation as resolved.
Show resolved Hide resolved
stepsFromCommands: {
maxArgumentLength: number;
maxArgumentDepth: number;
};
};
initialized: boolean;
testPlan: TestPlanV1 | null | undefined;
messages: CypressMessage[];
Expand Down
29 changes: 19 additions & 10 deletions packages/allure-cypress/src/reporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import type {
CypressTestStartMessage,
SpecContext,
} from "./model.js";
import { last } from "./utils.js";
import { DEFAULT_RUNTIME_CONFIG, last } from "./utils.js";

export class AllureCypress {
allureRuntime: ReporterRuntime;
Expand Down Expand Up @@ -489,19 +489,28 @@ export class AllureCypress {
};
}

const getInitialSpecState = (): AllureSpecState => ({
const createRuntimeState = (allureConfig?: AllureCypressConfig): AllureSpecState => ({
config: getRuntimeConfigDefaults(allureConfig),
initialized: false,
messages: [],
testPlan: parseTestPlan(),
});

/**
* Explicitly enables the selective run feature.
* @param config The Cypress configuration.
*/
export const enableTestPlan = (config: Cypress.PluginConfigOptions) => {
config.env.allure = getInitialSpecState();
return config;
const getRuntimeConfigDefaults = ({
stepsFromCommands: {
maxArgumentLength = DEFAULT_RUNTIME_CONFIG.stepsFromCommands.maxArgumentLength,
maxArgumentDepth = DEFAULT_RUNTIME_CONFIG.stepsFromCommands.maxArgumentDepth,
} = DEFAULT_RUNTIME_CONFIG.stepsFromCommands,
}: AllureCypressConfig = DEFAULT_RUNTIME_CONFIG): AllureSpecState["config"] => ({
stepsFromCommands: {
maxArgumentDepth,
maxArgumentLength,
},
});

const initializeRuntimeState = (cypressConfig: Cypress.PluginConfigOptions, allureConfig?: AllureCypressConfig) => {
cypressConfig.env.allure = createRuntimeState(allureConfig);
return cypressConfig;
};

/**
Expand Down Expand Up @@ -539,7 +548,7 @@ export const allureCypress = (
allureCypressReporter.attachToCypress(on);

if (cypressConfig && "env" in cypressConfig) {
enableTestPlan(cypressConfig);
initializeRuntimeState(cypressConfig, allureConfig);
}

return allureCypressReporter;
Expand Down
9 changes: 8 additions & 1 deletion packages/allure-cypress/src/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
getStatusFromError,
getUnfinishedStepsMessages,
isPromise,
serialize,
} from "allure-js-commons/sdk";
import type { RuntimeMessage } from "allure-js-commons/sdk";
import { getGlobalTestRuntime, setGlobalTestRuntime } from "allure-js-commons/sdk/runtime";
Expand All @@ -26,6 +27,7 @@ import { ALLURE_REPORT_STEP_COMMAND } from "./model.js";
import {
dropCurrentTest,
enqueueRuntimeMessage,
getConfig,
getCurrentTest,
getRuntimeMessages,
setCurrentTest,
Expand Down Expand Up @@ -361,11 +363,16 @@ export const reportTestSkip = (test: CypressTest) => {
};

export const reportCommandStart = (command: CypressCommand) => {
const {
stepsFromCommands: { maxArgumentDepth, maxArgumentLength },
} = getConfig();
enqueueRuntimeMessage({
type: "cypress_command_start",
data: {
name: `Command "${command.attributes.name}"`,
args: command.attributes.args.map((arg) => (typeof arg === "string" ? arg : JSON.stringify(arg, null, 2))),
args: command.attributes.args.map((arg) =>
serialize(arg, { maxDepth: maxArgumentDepth, maxLength: maxArgumentLength }),
),
start: Date.now(),
},
});
Expand Down
4 changes: 4 additions & 0 deletions packages/allure-cypress/src/state.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import type { AllureSpecState, CypressMessage, CypressTest } from "./model.js";
import { DEFAULT_RUNTIME_CONFIG } from "./utils.js";

export const getAllureState = () => {
let state = Cypress.env("allure") as AllureSpecState;
if (!state) {
state = {
config: DEFAULT_RUNTIME_CONFIG,
initialized: false,
messages: [],
testPlan: undefined,
Expand Down Expand Up @@ -41,3 +43,5 @@ export const setCurrentTest = (test: CypressTest) => {
export const dropCurrentTest = () => {
getAllureState().currentTest = undefined;
};

export const getConfig = () => getAllureState().config;
7 changes: 7 additions & 0 deletions packages/allure-cypress/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ import { ALLURE_REPORT_STEP_COMMAND, ALLURE_REPORT_SYSTEM_HOOK } from "./model.j
import type { CypressCommand, CypressHook, CypressSuite, CypressTest } from "./model.js";
import { getAllureTestPlan } from "./state.js";

export const DEFAULT_RUNTIME_CONFIG = {
stepsFromCommands: {
maxArgumentLength: 128,
maxArgumentDepth: 3,
},
};

export const uint8ArrayToBase64 = (data: unknown) => {
// @ts-ignore
const u8arrayLike = Array.isArray(data) || data.buffer;
Expand Down
Loading
Loading