diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..39bbd26 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,4 @@ +{ + "image": "mcr.microsoft.com/devcontainers/universal:2", + "features": {} +} diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..06b0b86 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,4 @@ +# These are supported funding model platforms + +github: [filiphric] +custom: ['https://filiphric.com/workshops'] diff --git a/CHANGELOG.md b/CHANGELOG.md index d0e0c32..6fefe5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,34 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [2.11.1](https://github.com/filiphric/cypress-plugin-api/compare/v2.11.0...v2.11.1) (2023-05-15) + + +### Bug Fixes + +* types for env object being wrongly set as required ([8a1a995](https://github.com/filiphric/cypress-plugin-api/commits/8a1a9954eebaa16ed505cd2715d4ba77d07c1d9b)) + +## [2.11.0](https://github.com/filiphric/cypress-plugin-api/compare/v2.10.5...v2.11.0) (2023-03-17) + + +### Features + +* add support for hiding query parameters ([9122abc](https://github.com/filiphric/cypress-plugin-api/commits/9122abcb68e683b5e2d8da6d35e703de593b8e73)) + +### [2.10.5](https://github.com/filiphric/cypress-plugin-api/compare/v2.10.4...v2.10.5) (2023-03-17) + + +### Bug Fixes + +* snapshot handling that causes unexpected errors ([f60021d](https://github.com/filiphric/cypress-plugin-api/commits/f60021d0f3c52cc7e6fc60955279362a848f8e90)) + +### [2.10.4](https://github.com/filiphric/cypress-plugin-api/compare/v2.10.3...v2.10.4) (2023-03-17) + + +### Bug Fixes + +* make size attribute optional ([7950f38](https://github.com/filiphric/cypress-plugin-api/commits/7950f38d04a1197d2b6600e5fb7a6f1be058cf9f)) + ### [2.10.3](https://github.com/filiphric/cypress-plugin-api/compare/v2.10.2...v2.10.3) (2023-02-03) diff --git a/README.md b/README.md index 33e7d1e..f56af19 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,8 @@ it('my secret test', { hideCredentialsOptions: { headers: ['authorization'], auth: ['pass'], - body: ['username'] + body: ['username'], + query: ['password'] } } }, () => { @@ -115,6 +116,9 @@ it('my secret test', { }, body: { username: Cypress.env('myUser') // hidden + }, + qs: { + password: Cypress.env('password') // hidden } }) diff --git a/cypress/e2e/authorization.cy.ts b/cypress/e2e/authorization.cy.ts index 3764ef3..a882d28 100644 --- a/cypress/e2e/authorization.cy.ts +++ b/cypress/e2e/authorization.cy.ts @@ -130,6 +130,29 @@ describe('Hiding credentials by defining them', () => { }); + it('hides credentials in query', { + env: { + hideCredentials: true, + hideCredentialsOptions: { + qs: ['password'] + } + } + }, () => { + + cy.api({ + method: 'POST', + url: '/', + qs: { + password: 'secret' + } + }) + + cy.get('[data-cy="query"]') + .should('contain', '******') + .should('contain', 'password') + + }); + }); describe('Showing credentials', () => { diff --git a/package-lock.json b/package-lock.json index 5684f91..d3e2062 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "cypress-plugin-api", - "version": "2.10.3", + "version": "2.11.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "cypress-plugin-api", - "version": "2.10.3", + "version": "2.11.1", "license": "ISC", "dependencies": { "highlight.js": "11.4.0", @@ -42,7 +42,7 @@ "vite": "^3.1.4" }, "peerDependencies": { - "cypress": ">=3" + "cypress": ">=10" } }, "node_modules/@babel/code-frame": { @@ -12171,7 +12171,8 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", - "dev": true + "dev": true, + "requires": {} }, "@octokit/plugin-rest-endpoint-methods": { "version": "6.6.2", @@ -12644,7 +12645,8 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-3.1.2.tgz", "integrity": "sha512-3zxKNlvA3oNaKDYX0NBclgxTQ1xaFdL7PzwF6zj9tGFziKwmBa3Q/6XcJQxudlT81WxDjEhHmevvIC4Orc1LhQ==", - "dev": true + "dev": true, + "requires": {} }, "@vue/compiler-core": { "version": "3.2.41", @@ -12765,7 +12767,8 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true + "dev": true, + "requires": {} }, "acorn-node": { "version": "1.8.2", @@ -13771,7 +13774,8 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-4.2.0.tgz", "integrity": "sha512-NkANeMnaHrlaSSlpKGyvn2R4rqUDeE/9E5YHx+b4nwo0R8dZyAqcih8/gxpCZvqWP9Vf6xuLpMSzSgdVEIM78g==", - "dev": true + "dev": true, + "requires": {} }, "create-require": { "version": "1.1.1", diff --git a/package.json b/package.json index c41cf6e..2b475d2 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "author": "Filip Hric (https://filiphric.com/)", "license": "ISC", "name": "cypress-plugin-api", - "version": "2.10.3", + "version": "2.11.1", "keywords": [ "cypress", "api", @@ -69,7 +69,7 @@ "vite": "^3.1.4" }, "peerDependencies": { - "cypress": ">=3" + "cypress": ">=10" }, "dependencies": { "highlight.js": "11.4.0", diff --git a/src/components/StatusPanel.vue b/src/components/StatusPanel.vue index 22bd102..7ae97d5 100644 --- a/src/components/StatusPanel.vue +++ b/src/components/StatusPanel.vue @@ -14,7 +14,7 @@ class="mx-2 font-mono text-cy-green" >{{ time }} ms

-

+

Size: { diff --git a/src/modules/handleResponse.ts b/src/modules/handleResponse.ts index 0583136..df9d26b 100644 --- a/src/modules/handleResponse.ts +++ b/src/modules/handleResponse.ts @@ -2,7 +2,7 @@ import { removeStyles } from '@modules/removeStyles' import setCookie from 'set-cookie-parser'; import { convertSize } from '@utils/convertSize'; import { calculateSize } from '@utils/calculateSize'; -import { ApiRequestOptions, ApiResponseBody, RequestProps } from 'src/types'; +import { ApiRequestOptions, ApiResponseBody, RequestProps } from '../types'; import { transform } from "@modules/transform"; import { getState } from '@utils/getState'; import { App } from 'vue'; @@ -17,7 +17,7 @@ export const handleResponse = (res: ApiResponseBody, options: ApiRequestOptions, name: options.method || 'GET', autoEnd: false, message: `${options.url}` - }) + }).snapshot('request') const { body, status, headers, statusText, duration } = res @@ -69,40 +69,46 @@ export const handleResponse = (res: ApiResponseBody, options: ApiRequestOptions, props[index].responseHeaders.formatted = transform(headers) // count content size from header if available, or calculate manually - const size = contentLengthHeader ? parseInt(contentLengthHeader) : calculateSize(props[index].responseBody.body.value) + const size = contentLengthHeader ? parseInt(contentLengthHeader) : calculateSize(props[index].responseBody.body?.value) props[index].size = convertSize(size) // convert to readable format (kB, MB...) res.size = size const yielded = res - // we need to make sure we do the snapshot at a right moment - cy.get(`#${props[index].id}`, { log: false }).then(($el) => { + const findSnapshotElement = () => { + return Cypress.$(`#${props[index].id}`, { log: false }) + } - // add response to console output - log.set({ - consoleProps() { - return { - yielded + // we need to make sure we do the snapshot at a right moment + cy.window({ log: false }) + .then(findSnapshotElement) + .then(($el) => { + + // add response to console output + log.set({ + consoleProps() { + return { + yielded + } } - } - }) + }) - // save all props to current window to be loaded - window.props[testId] = props + // save all props to current window to be loaded + window.props[testId] = props - log.set({ $el }); - log.snapshot('snapshot').end() + log.set({ $el }); + log.snapshot('response').end() - // scroll to the bottom - doc.getElementById('api-view-bottom')?.scrollIntoView() + // scroll to the bottom + doc.getElementById('api-view-bottom')?.scrollIntoView() - // if in snapshot mode, unmount plugin from view - if (Cypress.env('snapshotOnly')) { - app.unmount() - removeStyles() - } + // if in snapshot mode, unmount plugin from view + if (Cypress.env('snapshotOnly')) { + app.unmount() + removeStyles() + } - return res + return res - }) + }) } \ No newline at end of file diff --git a/src/modules/initialize.ts b/src/modules/initialize.ts index 7d7010d..3e21783 100644 --- a/src/modules/initialize.ts +++ b/src/modules/initialize.ts @@ -1,5 +1,5 @@ import { getState } from '@utils/getState' -import { RequestProps } from "src/types" +import { RequestProps } from "../types" import { reactive, createApp } from "vue" import App from "../components/App.vue"; import { mountPlugin } from "./mountPlugin"; diff --git a/src/modules/transformData.ts b/src/modules/transformData.ts index 1cee466..fee8c97 100644 --- a/src/modules/transformData.ts +++ b/src/modules/transformData.ts @@ -1,4 +1,4 @@ -import { RequestProps } from "src/types" +import { RequestProps } from "../types" import { transform } from "./transform" export const transformData = (props: RequestProps[], index: number) => { diff --git a/src/types.ts b/src/types.ts index b2b1c15..fca3f3f 100644 --- a/src/types.ts +++ b/src/types.ts @@ -90,7 +90,7 @@ declare global { env(object: PluginEnvOptions): void; } interface TestConfigOverrides { - env?: PluginEnvOptions + env?: Partial } } interface Window { @@ -109,6 +109,7 @@ export interface HideCredentialsOptions { auth?: string[] headers?: string[] body?: string[] + qs?: string[] } export interface ApiRequestOptions extends Cypress.RequestOptions { diff --git a/src/utils/anonymize.ts b/src/utils/anonymize.ts index ce33d1a..6bb201e 100644 --- a/src/utils/anonymize.ts +++ b/src/utils/anonymize.ts @@ -8,6 +8,7 @@ export const anonymize = (options: RequestProps) => { auth: [], body: [], headers: [], + qs: [], ...Cypress.env('hideCredentialsOptions') } @@ -37,5 +38,12 @@ export const anonymize = (options: RequestProps) => { } }) + anonymizeOptions.qs?.forEach(k => { + if (options.query.body && options.query.body[k as keyof Cypress.RequestBody]) { + // @ts-ignore until I figure out how to fix this + options.query.body[k] = options?.query.body[k].replace(/./g, '*') + } + }) + return options } \ No newline at end of file