Skip to content

Commit

Permalink
Merge branch 'main' into feature/39-record-pacts-for-cyintercept
Browse files Browse the repository at this point in the history
* main:
  Improved c8yclient adding of default content types.
  Add date() to C8yPactRecord
  Always add type to pact record auth.
  Added runner/ test:open script
  Fixed runner:yalc script to run in dist/ folder.
  Removed adding content-type header for c8y/client request header. Also removing content-type header for tenant/currentTenant.
  Store strictMatching setting in pact info. Use in runner when running the tests.
  c8ypact default logging is now false.
  Fixed use of wrong C8Y_LOGGED_IN_USERALIAS env variable. Now using C8Y_LOGGED_IN_USER_ALIAS.
  Fixed setLanguage static response interception  (#42)
  • Loading branch information
thomaswinkler committed Jan 13, 2024
2 parents 4c1cf94 + 7fdba43 commit 4f5e35e
Show file tree
Hide file tree
Showing 15 changed files with 328 additions and 45 deletions.
23 changes: 17 additions & 6 deletions lib/commands/c8yclient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,23 @@ window.fetch = async function (url, fetchOptions) {
logOnce = true;
}

// client.tenant.current() does add content-type header for some reason. probably mistaken accept header.
// as this is not required, remove it to avoid special handling in pact matching against recordings
// not created by c8y/client.
if (_.endsWith(toUrlString(url), "/tenant/currentTenant")) {
// @ts-ignore
fetchOptions.headers = _.omit(fetchOptions.headers, ["content-type"]);
} else {
// add json content type if body is present and content-type is not set
const method = fetchOptions?.method || "GET";
if (fetchOptions?.body && method !== "GET" && method != "HEAD") {
fetchOptions.headers = {
"content-type": "application/json",
...fetchOptions.headers,
};
}
}

let startTime: number = Date.now();
const fetchPromise: Promise<Response> = window.fetchStub(url, fetchOptions);

Expand Down Expand Up @@ -508,9 +525,6 @@ function runClient(
prevSubject: any,
baseUrl: string
) {
client._client.core.defaultHeaders = {
"content-type": "application/json",
};
storeClient(client);
if (!fns) {
// return Cypress.isCy(client) ? client : cy.wrap(client._client, { log: false });
Expand All @@ -529,9 +543,6 @@ function authenticateClient(
): Cypress.Chainable<C8yClient> {
return cy.then(async () => {
const clientCore = new FetchClient(auth, baseUrl);
clientCore.defaultHeaders = {
"content-type": "application/json",
};
const res = await clientCore.fetch("/tenant/currentTenant");
if (res.status !== 200) {
throwError(makeErrorMessage(res.responseObj));
Expand Down
25 changes: 18 additions & 7 deletions lib/commands/general.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Cypress.Commands.add("hideCookieBanner", () => {
Cypress.on("window:before:load", (window) => {
window.localStorage.setItem(COOKIE_NAME, COOKIE_VALUE);
});
window.localStorage.setItem(COOKIE_NAME, COOKIE_VALUE);

Cypress.log({
name: "hideCookieBanner",
Expand Down Expand Up @@ -45,6 +46,7 @@ Cypress.Commands.add("setLanguage", (lang) => {

Cypress.log({
name: "setLanguage",
message: lang,
consoleProps: () => {},
});
cy.intercept(
Expand All @@ -53,13 +55,22 @@ Cypress.Commands.add("setLanguage", (lang) => {
url: "/inventory/managedObjects?fragmentType=language*",
},
(req) => {
const languageFragment = req.query.fragmentType.toString();
const body = {
id: "123",
type: "c8y_UserPreference",
[languageFragment]: lang,
};
req.reply({ statusCode: 200, body });
req.continue((res) => {
const languageFragment = req.query.fragmentType.toString();
if (res.body[languageFragment]) {
res.body[languageFragment] = lang;
} else if (
res.body.managedObjects &&
_.isArrayLike(res.body.managedObjects)
) {
res.body.managedObjects.forEach((mo) => {
if (mo[languageFragment]) {
mo[languageFragment] = lang;
}
});
}
res.send();
});
}
);

Expand Down
48 changes: 43 additions & 5 deletions lib/pacts/c8ypact.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ declare global {
* Tenant when recording the pact.
*/
tenant?: string;
/**
* Setting of strict matching when recording the pact.
*/
strictMatching?: boolean;
}

/**
Expand Down Expand Up @@ -193,16 +197,35 @@ declare global {
* the created object id.
*/
interface C8yPactRecord {
/**
* Request of the record.
*/
request: C8yPactRequest;
/**
* Response of the record.
*/
response: C8yPactResponse<any>;
/**
* Configuration options used for the request.
*/
options: C8yClientOptions;
/**
* Auth information used for the request. Can be Basic or Cookie auth. Contains username and possibly alias.
*/
auth: C8yAuthOptions;
/**
* Id of an object created by the request. Used for mapping when running the recording.
*/
createdObject: string;

/**
* Converts the C8yPactRecord to a Cypress.Response object.
*/
toCypressResponse(): Cypress.Response<any>;
/**
* Returns the date of the response.
*/
date(): Date;
}

/**
Expand Down Expand Up @@ -269,6 +292,14 @@ export class C8yDefaultPactRecord implements C8yPactRecord {
return createPactRecord(response, client);
}

date(): Date {
const date = _.get(this.response, "headers.date");
if (date) {
return new Date(date);
}
return null;
}

/**
* Converts the C8yPactRecord to a Cypress.Response object.
*/
Expand Down Expand Up @@ -305,7 +336,7 @@ Cypress.c8ypact = {
pactRunner: new C8yDefaultPactRunner(),
failOnMissingPacts: true,
strictMatching: true,
debugLog: true,
debugLog: false,
};

function debugLogger(): Cypress.Loggable {
Expand Down Expand Up @@ -475,7 +506,7 @@ function currentNextRecord(): Cypress.Chainable<{

function createPactInfo(id: string, client: C8yClient = null): C8yPactInfo {
const c8ypact = Cypress.config().c8ypact;
const info = {
const info: C8yPactInfo = {
title: Cypress.currentTest?.titlePath || [],
id,
preprocessor: {
Expand All @@ -493,6 +524,7 @@ function createPactInfo(id: string, client: C8yClient = null): C8yPactInfo {
version: Cypress.env("C8Y_VERSION") && {
system: Cypress.env("C8Y_VERSION"),
},
strictMatching: Cypress.c8ypact.strictMatching,
};
return info;
}
Expand Down Expand Up @@ -548,16 +580,22 @@ function createPactRecord(
);

const envUser = Cypress.env("C8Y_LOGGED_IN_USER");
const envAlias = Cypress.env("C8Y_LOGGED_IN_USERALIAS");
const envAlias = Cypress.env("C8Y_LOGGED_IN_USER_ALIAS");
const envAuth = {
...(envUser && { user: envUser }),
...(envAlias && { userAlias: envAlias }),
...(envAlias && { type: "CookieAuth" }),
};

if (client?._auth) {
// do not pick the password. passwords must not be stored in the pact.
pact.auth = { ...envAuth, ..._.pick(client._auth, ["user", "userAlias"]) };
pact.auth.type = client._auth.constructor.name;
pact.auth = _.defaultsDeep(
client._auth,
_.pick(envAuth, ["user", "userAlias", "type"])
);
if (client._auth.constructor != null) {
pact.auth.type = client._auth.constructor.name;
}
}
if (!pact.auth && (envUser || envAlias)) {
pact.auth = envAuth;
Expand Down
2 changes: 2 additions & 0 deletions lib/pacts/runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ export class C8yDefaultPactRunner implements C8yPactRunner {
this.idMapper = {};
for (const record of pact?.records) {
cy.then(() => {
Cypress.c8ypact.strictMatching = pact.info?.strictMatching || true;

const url = this.createURL(record, pact.info);
const clientFetchOptions = this.createFetchOptions(record, pact.info);

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
"description": "Cypress commands for Cumulocity IoT",
"main": "lib/commands/index.js",
"scripts": {
"start-server": "http-server test/cypress/app/ --port 8080 --silent --mimetypes test/custom_mime_types.types",
"start-server": "http-server test/cypress/app/ --port 8080 --silent --mimetypes test/custom_mime_types.types --ext json",
"test": "TZ=Europe/Berlin start-server-and-test start-server http://localhost:8080 test:run",
"test:run": "TZ=Europe/Berlin cypress run --project test --browser chrome --config video=false",
"test:open": "TZ=Europe/Berlin start-server-and-test start-server http://localhost:8080 debug",
"debug": "CYPRESS_REMOTE_DEBUGGING_PORT=9222 cypress open --project test",
"clean": "rimraf dist/ && rimraf runner/dist/ && rimraf runner/.yalc && rimraf runner/yalc.lock",
"copy-files": "copyfiles lib/**/*.*js lib/**/*.d.ts README.md package.json dist/",
"build": "npm run clean && npm run copy-files && tsc && cd dist/ && npm run clean-package-json",
"runner:yalc": "npm run clean && npm run build && yalc publish && cd runner && yalc add cumulocity-cypress",
"runner:yalc": "npm run clean && npm run build && cd dist/ && yalc publish && cd ../runner && yalc add cumulocity-cypress",
"clean-package-json": "npm pkg delete 'devDependencies' && npm pkg delete 'scripts'"
},
"repository": {
Expand Down
1 change: 1 addition & 0 deletions runner/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"description": "Cypress runner for Cumulocity pact recordings",
"scripts": {
"test": "cypress run --config-file cypress.config.js --spec cypress/e2e/pact-runner.cy.ts",
"test:open": "cypress open",
"docker": "docker build --platform linux/arm64 -t c8ypact-runner --target prod .",
"docker:dev": "docker build --platform linux/arm64 -t c8ypact-runner --target dev ."
},
Expand Down
2 changes: 1 addition & 1 deletion test/custom_mime_types.types
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# This file is an example of the Apache .types file format for describing mime-types.
# Other example: http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
application/json json
application/json json
43 changes: 43 additions & 0 deletions test/cypress/app/inventory/managedObjects.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"self": "https://t617206445.eu-latest.cumulocity.com/inventory/managedObjects?pageSize=5&fragmentType=languageXYZ&currentPage=1",
"next": "https://t617206445.eu-latest.cumulocity.com/inventory/managedObjects?pageSize=5&fragmentType=languageXYZ&currentPage=2",
"managedObjects": [
{
"self": "https://t617206445.eu-latest.cumulocity.com/inventory/managedObjects/4228241",
"id": "4228241",
"type": "c8y_UserPreference",
"lastUpdated": "2023-09-04T07:17:51.365Z",
"creationTime": "2021-07-20T13:19:27.372Z",
"owner": "test@test.de",
"childDevices": {
"self": "https://t617206445.eu-latest.cumulocity.com/inventory/managedObjects/4228241/childDevices",
"references": []
},
"childAssets": {
"self": "https://t617206445.eu-latest.cumulocity.com/inventory/managedObjects/4228241/childAssets",
"references": []
},
"childAdditions": {
"self": "https://t617206445.eu-latest.cumulocity.com/inventory/managedObjects/4228241/childAdditions",
"references": []
},
"deviceParents": {
"self": "https://t617206445.eu-latest.cumulocity.com/inventory/managedObjects/4228241/deviceParents",
"references": []
},
"assetParents": {
"self": "https://t617206445.eu-latest.cumulocity.com/inventory/managedObjects/4228241/assetParents",
"references": []
},
"additionParents": {
"self": "https://t617206445.eu-latest.cumulocity.com/inventory/managedObjects/4228241/additionParents",
"references": []
},
"languageXYZ": "en"
}
],
"statistics": {
"pageSize": 5,
"currentPage": 1
}
}
8 changes: 4 additions & 4 deletions test/cypress/e2e/administration.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ describe("administration", () => {
password: "mypassword",
tenant: "t12345678",
},
headers: { UseXBasic: true, "content-type": "application/json" },
headers: { UseXBasic: true },
method: "DELETE",
});
});
Expand Down Expand Up @@ -77,7 +77,7 @@ describe("administration", () => {
password: "mypassword",
tenant: "t12345678",
},
headers: { UseXBasic: true, "content-type": "application/json" },
headers: { UseXBasic: true },
method: "DELETE",
});
});
Expand Down Expand Up @@ -113,7 +113,7 @@ describe("administration", () => {
password: "mypassword",
tenant: "t12345678",
},
headers: { UseXBasic: true, "content-type": "application/json" },
headers: { UseXBasic: true },
});
});
});
Expand All @@ -132,7 +132,7 @@ describe("administration", () => {
password: "mypassword",
tenant: "t12345678",
},
headers: { UseXBasic: true, "content-type": "application/json" },
headers: { UseXBasic: true },
});
});
});
Expand Down
Loading

0 comments on commit 4f5e35e

Please sign in to comment.