diff --git a/README.md b/README.md index 7729215..b71fea2 100644 --- a/README.md +++ b/README.md @@ -47,11 +47,31 @@ Setup the Keycloak configuration in `cypress.json` configuration file: } ``` -You can override this settings for some tests using [Enviroment variabiles](https://docs.cypress.io/guides/guides/environment-variables.html). +You can override this settings for some tests using [Environment variables](https://docs.cypress.io/guides/guides/environment-variables.html). ### Login commands for E2E Tests -For logging in with Keycloak you must create a [fixture](https://docs.cypress.io/api/commands/fixture.html) containing the user credentials under the directory `cypress/fixtures/users`. For example you can create a file `cypress/fixtures/users/user.json` with this content: +For logging in with Keycloak there are two possibilities +#### Using Variables + +This is the recommended approach, since it enables the usage of [Environment variables](https://docs.cypress.io/guides/guides/environment-variables.html) for production environments. + +```typescript +describe("Keycloak Login", () => { + beforeEach(() => { + cy.kcLogout(); + cy.kcLogin({ + username: "user", + password: "password" + }); + cy.visit("/"); + }); +}); +``` + +#### Using fixtures + +Create a [fixture](https://docs.cypress.io/api/commands/fixture.html) containing the user credentials under the directory `cypress/fixtures/users`. For example you can create a file `cypress/fixtures/users/user.json` with this content: ```json { @@ -143,7 +163,7 @@ describe("Keycloak Fake Login", () => { #### Session Status iframe -At the moment within Cypress is not possible to mock iframe loading and APIs called from an iframe. For this reason, when you use `kcFakeLogin` you have to disable the Session Status iframe, otherwise the Javascript adapter will redirect you to the real Keyacloak instance. You can disable it only when the app is running inside Cypress: +At the moment within Cypress is not possible to mock iframe loading and APIs called from an iframe. For this reason, when you use `kcFakeLogin` you have to disable the Session Status iframe, otherwise the Javascript adapter will redirect you to the real Keycloak instance. You can disable it only when the app is running inside Cypress: ```typescript const checkLoginIframe = window.Cypress ? false : true; diff --git a/cypress/integration/fake-login.spec.ts b/cypress/integration/fake-login.spec.ts index 8c71a79..44cc81d 100644 --- a/cypress/integration/fake-login.spec.ts +++ b/cypress/integration/fake-login.spec.ts @@ -33,3 +33,93 @@ describe("Keycloak Fake Login", () => { cy.get("#output").should("contain.text", "Init Success (Authenticated)"); }); }); + +describe("Keycloak Fake Login with runtime credentials", () => { + it("should show user as authenticated", () => { + cy.kcFakeLogin({ + fakeLogin: { + access_token: "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJGSjg2R2NGM2pUYk5MT2NvNE52WmtVQ0lVbWZZQ3FvcXRPUWVNZmJoTmxFIn0.eyJqdGkiOiJhZTZhMmQ4Zi1lNTZiLTQ4MWQtOThhMS1hNzU5NzMzNDg1ZGYiLCJleHAiOjE1ODAxMjYyMjEsIm5iZiI6MCwiaWF0IjoxNTgwMTI1OTIxLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODEvYXV0aC9yZWFsbXMvZXhhbXBsZSIsImF1ZCI6ImFjY291bnQiLCJzdWIiOiI2N2MzMzEzNC1hYWExLTRkODgtYTdjZS0zNTQwOGQwZjEzMzIiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJqcy1jb25zb2xlIiwibm9uY2UiOiJiZjJmODA2OS0yYTNmLTQzY2EtOWI2Yy1kOTk2NzE4MDZmNTYiLCJhdXRoX3RpbWUiOjE1ODAxMjU5MjEsInNlc3Npb25fc3RhdGUiOiI2N2U2YWZjNS03OTE3LTQ3MjAtYmViNy0xYWM1ZDFmNDlkOTUiLCJhY3IiOiIxIiwiYWxsb3dlZC1vcmlnaW5zIjpbImh0dHA6Ly9sb2NhbGhvc3Q6ODA4MCJdLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsidXNlciJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoib3BlbmlkIGVtYWlsIHByb2ZpbGUiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJTYW1wbGUgVXNlciIsInByZWZlcnJlZF91c2VybmFtZSI6InVzZXIiLCJnaXZlbl9uYW1lIjoiU2FtcGxlIiwiZmFtaWx5X25hbWUiOiJVc2VyIiwiZW1haWwiOiJzYW1wbGUtdXNlckBleGFtcGxlIn0.Cb_WD_L2XyWUCt9h6QUs6aTxbGbOod9zbE2hfeNVMzGhKc2t22CgvaiUbhs1YmETGxGd7_ABR3G-Z99pmJQYDydEo4AdLfqztssJOr53mAgal_J64JIs0sl0e26sE3Cdd6K0ZS0W3eHHNmlGxOFL5erphWN53BZ-HX9JG0I3K1c", + refresh_token: "eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJmZGIyYmYyYS1jMDI1LTRmODEtYWZmMi1hYTJlY2FjNzg1MTYifQ.eyJqdGkiOiJjYWE0YTllYi04NGZhLTRhMTMtYjZjZS0yMjM4ZmVlYzYyM2UiLCJleHAiOjE1ODAxMjc3MjEsIm5iZiI6MCwiaWF0IjoxNTgwMTI1OTIxLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODEvYXV0aC9yZWFsbXMvZXhhbXBsZSIsImF1ZCI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODA4MS9hdXRoL3JlYWxtcy9leGFtcGxlIiwic3ViIjoiNjdjMzMxMzQtYWFhMS00ZDg4LWE3Y2UtMzU0MDhkMGYxMzMyIiwidHlwIjoiUmVmcmVzaCIsImF6cCI6ImpzLWNvbnNvbGUiLCJub25jZSI6ImJmMmY4MDY5LTJhM2YtNDNjYS05YjZjLWQ5OTY3MTgwNmY1NiIsImF1dGhfdGltZSI6MCwic2Vzc2lvbl9zdGF0ZSI6IjY3ZTZhZmM1LTc5MTctNDcyMC1iZWI3LTFhYzVkMWY0OWQ5NSIsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJ1c2VyIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJvcGVuaWQgZW1haWwgcHJvZmlsZSJ9.6BVpoZCsZbb6vPpdFwspAFT8lYCLYyNrcrOU-27VMaY", + id_token: "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJGSjg2R2NGM2pUYk5MT2NvNE52WmtVQ0lVbWZZQ3FvcXRPUWVNZmJoTmxFIn0.eyJqdGkiOiIzNjMxZTZlNi03MTQ1LTQyZWUtOWU2Yi01MDFkNDFhZGI1NGYiLCJleHAiOjE1ODAxMjYyMjEsIm5iZiI6MCwiaWF0IjoxNTgwMTI1OTIxLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODEvYXV0aC9yZWFsbXMvZXhhbXBsZSIsImF1ZCI6ImpzLWNvbnNvbGUiLCJzdWIiOiI2N2MzMzEzNC1hYWExLTRkODgtYTdjZS0zNTQwOGQwZjEzMzIiLCJ0eXAiOiJJRCIsImF6cCI6ImpzLWNvbnNvbGUiLCJub25jZSI6ImJmMmY4MDY5LTJhM2YtNDNjYS05YjZjLWQ5OTY3MTgwNmY1NiIsImF1dGhfdGltZSI6MTU4MDEyNTkyMSwic2Vzc2lvbl9zdGF0ZSI6IjY3ZTZhZmM1LTc5MTctNDcyMC1iZWI3LTFhYzVkMWY0OWQ5NSIsImFjciI6IjEiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJTYW1wbGUgVXNlciIsInByZWZlcnJlZF91c2VybmFtZSI6InVzZXIiLCJnaXZlbl9uYW1lIjoiU2FtcGxlIiwiZmFtaWx5X25hbWUiOiJVc2VyIiwiZW1haWwiOiJzYW1wbGUtdXNlckBleGFtcGxlIn0.pDHa-ioVBiHNRHiu0atnKTNHn2d_NPMFYBoiQXTuZ4Wj0jfwUqsOD1KIC1t5Q1-OBNLjnzBRhm8qfvg3Vm-B7mNchIJkGOJlF8XcN7e1VyXOWb2yNvZ4TL5QtF_5aVx-_WgpajiUdQyKVEWtwMbb1qyKMVHH2vIxtzep9Sy2zek", + account: { + username: "user", + firstName: "Sample", + lastName: "User", + email: "sample-user@example", + emailVerified: false, + attributes: {} + } + } + }); + cy.get("#output").should("contain.text", "Init Success (Authenticated)"); + }); + + it("should get user data equal to fixture data", () => { + cy.kcFakeLogin({ + fakeLogin: { + access_token: "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJGSjg2R2NGM2pUYk5MT2NvNE52WmtVQ0lVbWZZQ3FvcXRPUWVNZmJoTmxFIn0.eyJqdGkiOiJhZTZhMmQ4Zi1lNTZiLTQ4MWQtOThhMS1hNzU5NzMzNDg1ZGYiLCJleHAiOjE1ODAxMjYyMjEsIm5iZiI6MCwiaWF0IjoxNTgwMTI1OTIxLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODEvYXV0aC9yZWFsbXMvZXhhbXBsZSIsImF1ZCI6ImFjY291bnQiLCJzdWIiOiI2N2MzMzEzNC1hYWExLTRkODgtYTdjZS0zNTQwOGQwZjEzMzIiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJqcy1jb25zb2xlIiwibm9uY2UiOiJiZjJmODA2OS0yYTNmLTQzY2EtOWI2Yy1kOTk2NzE4MDZmNTYiLCJhdXRoX3RpbWUiOjE1ODAxMjU5MjEsInNlc3Npb25fc3RhdGUiOiI2N2U2YWZjNS03OTE3LTQ3MjAtYmViNy0xYWM1ZDFmNDlkOTUiLCJhY3IiOiIxIiwiYWxsb3dlZC1vcmlnaW5zIjpbImh0dHA6Ly9sb2NhbGhvc3Q6ODA4MCJdLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsidXNlciJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoib3BlbmlkIGVtYWlsIHByb2ZpbGUiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJTYW1wbGUgVXNlciIsInByZWZlcnJlZF91c2VybmFtZSI6InVzZXIiLCJnaXZlbl9uYW1lIjoiU2FtcGxlIiwiZmFtaWx5X25hbWUiOiJVc2VyIiwiZW1haWwiOiJzYW1wbGUtdXNlckBleGFtcGxlIn0.Cb_WD_L2XyWUCt9h6QUs6aTxbGbOod9zbE2hfeNVMzGhKc2t22CgvaiUbhs1YmETGxGd7_ABR3G-Z99pmJQYDydEo4AdLfqztssJOr53mAgal_J64JIs0sl0e26sE3Cdd6K0ZS0W3eHHNmlGxOFL5erphWN53BZ-HX9JG0I3K1c", + refresh_token: "eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJmZGIyYmYyYS1jMDI1LTRmODEtYWZmMi1hYTJlY2FjNzg1MTYifQ.eyJqdGkiOiJjYWE0YTllYi04NGZhLTRhMTMtYjZjZS0yMjM4ZmVlYzYyM2UiLCJleHAiOjE1ODAxMjc3MjEsIm5iZiI6MCwiaWF0IjoxNTgwMTI1OTIxLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODEvYXV0aC9yZWFsbXMvZXhhbXBsZSIsImF1ZCI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODA4MS9hdXRoL3JlYWxtcy9leGFtcGxlIiwic3ViIjoiNjdjMzMxMzQtYWFhMS00ZDg4LWE3Y2UtMzU0MDhkMGYxMzMyIiwidHlwIjoiUmVmcmVzaCIsImF6cCI6ImpzLWNvbnNvbGUiLCJub25jZSI6ImJmMmY4MDY5LTJhM2YtNDNjYS05YjZjLWQ5OTY3MTgwNmY1NiIsImF1dGhfdGltZSI6MCwic2Vzc2lvbl9zdGF0ZSI6IjY3ZTZhZmM1LTc5MTctNDcyMC1iZWI3LTFhYzVkMWY0OWQ5NSIsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJ1c2VyIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJvcGVuaWQgZW1haWwgcHJvZmlsZSJ9.6BVpoZCsZbb6vPpdFwspAFT8lYCLYyNrcrOU-27VMaY", + id_token: "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJGSjg2R2NGM2pUYk5MT2NvNE52WmtVQ0lVbWZZQ3FvcXRPUWVNZmJoTmxFIn0.eyJqdGkiOiIzNjMxZTZlNi03MTQ1LTQyZWUtOWU2Yi01MDFkNDFhZGI1NGYiLCJleHAiOjE1ODAxMjYyMjEsIm5iZiI6MCwiaWF0IjoxNTgwMTI1OTIxLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODEvYXV0aC9yZWFsbXMvZXhhbXBsZSIsImF1ZCI6ImpzLWNvbnNvbGUiLCJzdWIiOiI2N2MzMzEzNC1hYWExLTRkODgtYTdjZS0zNTQwOGQwZjEzMzIiLCJ0eXAiOiJJRCIsImF6cCI6ImpzLWNvbnNvbGUiLCJub25jZSI6ImJmMmY4MDY5LTJhM2YtNDNjYS05YjZjLWQ5OTY3MTgwNmY1NiIsImF1dGhfdGltZSI6MTU4MDEyNTkyMSwic2Vzc2lvbl9zdGF0ZSI6IjY3ZTZhZmM1LTc5MTctNDcyMC1iZWI3LTFhYzVkMWY0OWQ5NSIsImFjciI6IjEiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJTYW1wbGUgVXNlciIsInByZWZlcnJlZF91c2VybmFtZSI6InVzZXIiLCJnaXZlbl9uYW1lIjoiU2FtcGxlIiwiZmFtaWx5X25hbWUiOiJVc2VyIiwiZW1haWwiOiJzYW1wbGUtdXNlckBleGFtcGxlIn0.pDHa-ioVBiHNRHiu0atnKTNHn2d_NPMFYBoiQXTuZ4Wj0jfwUqsOD1KIC1t5Q1-OBNLjnzBRhm8qfvg3Vm-B7mNchIJkGOJlF8XcN7e1VyXOWb2yNvZ4TL5QtF_5aVx-_WgpajiUdQyKVEWtwMbb1qyKMVHH2vIxtzep9Sy2zek", + account: { + username: "user", + firstName: "Sample", + lastName: "User", + email: "sample-user@example", + emailVerified: false, + attributes: {} + } + } + }); + cy.get("#output").should("contain.text", "Init Success (Authenticated)"); + + cy.findByText("Get Profile").click(); + + cy.fixture("users/user.json").then((userData: UserData) => { + cy.get("#output").should(el => { + const value = JSON.parse(el.text()); + expect(value).to.deep.equal(userData.fakeLogin?.account); + }); + }); + }); + + it("should go to the specified path with hash and show user as authenticated", () => { + cy.kcFakeLogin({ + fakeLogin: { + access_token: "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJGSjg2R2NGM2pUYk5MT2NvNE52WmtVQ0lVbWZZQ3FvcXRPUWVNZmJoTmxFIn0.eyJqdGkiOiJhZTZhMmQ4Zi1lNTZiLTQ4MWQtOThhMS1hNzU5NzMzNDg1ZGYiLCJleHAiOjE1ODAxMjYyMjEsIm5iZiI6MCwiaWF0IjoxNTgwMTI1OTIxLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODEvYXV0aC9yZWFsbXMvZXhhbXBsZSIsImF1ZCI6ImFjY291bnQiLCJzdWIiOiI2N2MzMzEzNC1hYWExLTRkODgtYTdjZS0zNTQwOGQwZjEzMzIiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJqcy1jb25zb2xlIiwibm9uY2UiOiJiZjJmODA2OS0yYTNmLTQzY2EtOWI2Yy1kOTk2NzE4MDZmNTYiLCJhdXRoX3RpbWUiOjE1ODAxMjU5MjEsInNlc3Npb25fc3RhdGUiOiI2N2U2YWZjNS03OTE3LTQ3MjAtYmViNy0xYWM1ZDFmNDlkOTUiLCJhY3IiOiIxIiwiYWxsb3dlZC1vcmlnaW5zIjpbImh0dHA6Ly9sb2NhbGhvc3Q6ODA4MCJdLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsidXNlciJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoib3BlbmlkIGVtYWlsIHByb2ZpbGUiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJTYW1wbGUgVXNlciIsInByZWZlcnJlZF91c2VybmFtZSI6InVzZXIiLCJnaXZlbl9uYW1lIjoiU2FtcGxlIiwiZmFtaWx5X25hbWUiOiJVc2VyIiwiZW1haWwiOiJzYW1wbGUtdXNlckBleGFtcGxlIn0.Cb_WD_L2XyWUCt9h6QUs6aTxbGbOod9zbE2hfeNVMzGhKc2t22CgvaiUbhs1YmETGxGd7_ABR3G-Z99pmJQYDydEo4AdLfqztssJOr53mAgal_J64JIs0sl0e26sE3Cdd6K0ZS0W3eHHNmlGxOFL5erphWN53BZ-HX9JG0I3K1c", + refresh_token: "eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJmZGIyYmYyYS1jMDI1LTRmODEtYWZmMi1hYTJlY2FjNzg1MTYifQ.eyJqdGkiOiJjYWE0YTllYi04NGZhLTRhMTMtYjZjZS0yMjM4ZmVlYzYyM2UiLCJleHAiOjE1ODAxMjc3MjEsIm5iZiI6MCwiaWF0IjoxNTgwMTI1OTIxLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODEvYXV0aC9yZWFsbXMvZXhhbXBsZSIsImF1ZCI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODA4MS9hdXRoL3JlYWxtcy9leGFtcGxlIiwic3ViIjoiNjdjMzMxMzQtYWFhMS00ZDg4LWE3Y2UtMzU0MDhkMGYxMzMyIiwidHlwIjoiUmVmcmVzaCIsImF6cCI6ImpzLWNvbnNvbGUiLCJub25jZSI6ImJmMmY4MDY5LTJhM2YtNDNjYS05YjZjLWQ5OTY3MTgwNmY1NiIsImF1dGhfdGltZSI6MCwic2Vzc2lvbl9zdGF0ZSI6IjY3ZTZhZmM1LTc5MTctNDcyMC1iZWI3LTFhYzVkMWY0OWQ5NSIsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJ1c2VyIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJvcGVuaWQgZW1haWwgcHJvZmlsZSJ9.6BVpoZCsZbb6vPpdFwspAFT8lYCLYyNrcrOU-27VMaY", + id_token: "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJGSjg2R2NGM2pUYk5MT2NvNE52WmtVQ0lVbWZZQ3FvcXRPUWVNZmJoTmxFIn0.eyJqdGkiOiIzNjMxZTZlNi03MTQ1LTQyZWUtOWU2Yi01MDFkNDFhZGI1NGYiLCJleHAiOjE1ODAxMjYyMjEsIm5iZiI6MCwiaWF0IjoxNTgwMTI1OTIxLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODEvYXV0aC9yZWFsbXMvZXhhbXBsZSIsImF1ZCI6ImpzLWNvbnNvbGUiLCJzdWIiOiI2N2MzMzEzNC1hYWExLTRkODgtYTdjZS0zNTQwOGQwZjEzMzIiLCJ0eXAiOiJJRCIsImF6cCI6ImpzLWNvbnNvbGUiLCJub25jZSI6ImJmMmY4MDY5LTJhM2YtNDNjYS05YjZjLWQ5OTY3MTgwNmY1NiIsImF1dGhfdGltZSI6MTU4MDEyNTkyMSwic2Vzc2lvbl9zdGF0ZSI6IjY3ZTZhZmM1LTc5MTctNDcyMC1iZWI3LTFhYzVkMWY0OWQ5NSIsImFjciI6IjEiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJTYW1wbGUgVXNlciIsInByZWZlcnJlZF91c2VybmFtZSI6InVzZXIiLCJnaXZlbl9uYW1lIjoiU2FtcGxlIiwiZmFtaWx5X25hbWUiOiJVc2VyIiwiZW1haWwiOiJzYW1wbGUtdXNlckBleGFtcGxlIn0.pDHa-ioVBiHNRHiu0atnKTNHn2d_NPMFYBoiQXTuZ4Wj0jfwUqsOD1KIC1t5Q1-OBNLjnzBRhm8qfvg3Vm-B7mNchIJkGOJlF8XcN7e1VyXOWb2yNvZ4TL5QtF_5aVx-_WgpajiUdQyKVEWtwMbb1qyKMVHH2vIxtzep9Sy2zek", + account: { + username: "user", + firstName: "Sample", + lastName: "User", + email: "sample-user@example", + emailVerified: false, + attributes: {} + } + } + }, "#/foobar"); + cy.url().should("be.equal", `${Cypress.config("baseUrl")}/#/foobar`); + cy.get("#output").should("contain.text", "Init Success (Authenticated)"); + }); + + it("should go to the specified path without hash and show user as authenticated", () => { + cy.kcFakeLogin({ + fakeLogin: { + access_token: "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJGSjg2R2NGM2pUYk5MT2NvNE52WmtVQ0lVbWZZQ3FvcXRPUWVNZmJoTmxFIn0.eyJqdGkiOiJhZTZhMmQ4Zi1lNTZiLTQ4MWQtOThhMS1hNzU5NzMzNDg1ZGYiLCJleHAiOjE1ODAxMjYyMjEsIm5iZiI6MCwiaWF0IjoxNTgwMTI1OTIxLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODEvYXV0aC9yZWFsbXMvZXhhbXBsZSIsImF1ZCI6ImFjY291bnQiLCJzdWIiOiI2N2MzMzEzNC1hYWExLTRkODgtYTdjZS0zNTQwOGQwZjEzMzIiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJqcy1jb25zb2xlIiwibm9uY2UiOiJiZjJmODA2OS0yYTNmLTQzY2EtOWI2Yy1kOTk2NzE4MDZmNTYiLCJhdXRoX3RpbWUiOjE1ODAxMjU5MjEsInNlc3Npb25fc3RhdGUiOiI2N2U2YWZjNS03OTE3LTQ3MjAtYmViNy0xYWM1ZDFmNDlkOTUiLCJhY3IiOiIxIiwiYWxsb3dlZC1vcmlnaW5zIjpbImh0dHA6Ly9sb2NhbGhvc3Q6ODA4MCJdLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsidXNlciJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoib3BlbmlkIGVtYWlsIHByb2ZpbGUiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJTYW1wbGUgVXNlciIsInByZWZlcnJlZF91c2VybmFtZSI6InVzZXIiLCJnaXZlbl9uYW1lIjoiU2FtcGxlIiwiZmFtaWx5X25hbWUiOiJVc2VyIiwiZW1haWwiOiJzYW1wbGUtdXNlckBleGFtcGxlIn0.Cb_WD_L2XyWUCt9h6QUs6aTxbGbOod9zbE2hfeNVMzGhKc2t22CgvaiUbhs1YmETGxGd7_ABR3G-Z99pmJQYDydEo4AdLfqztssJOr53mAgal_J64JIs0sl0e26sE3Cdd6K0ZS0W3eHHNmlGxOFL5erphWN53BZ-HX9JG0I3K1c", + refresh_token: "eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJmZGIyYmYyYS1jMDI1LTRmODEtYWZmMi1hYTJlY2FjNzg1MTYifQ.eyJqdGkiOiJjYWE0YTllYi04NGZhLTRhMTMtYjZjZS0yMjM4ZmVlYzYyM2UiLCJleHAiOjE1ODAxMjc3MjEsIm5iZiI6MCwiaWF0IjoxNTgwMTI1OTIxLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODEvYXV0aC9yZWFsbXMvZXhhbXBsZSIsImF1ZCI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODA4MS9hdXRoL3JlYWxtcy9leGFtcGxlIiwic3ViIjoiNjdjMzMxMzQtYWFhMS00ZDg4LWE3Y2UtMzU0MDhkMGYxMzMyIiwidHlwIjoiUmVmcmVzaCIsImF6cCI6ImpzLWNvbnNvbGUiLCJub25jZSI6ImJmMmY4MDY5LTJhM2YtNDNjYS05YjZjLWQ5OTY3MTgwNmY1NiIsImF1dGhfdGltZSI6MCwic2Vzc2lvbl9zdGF0ZSI6IjY3ZTZhZmM1LTc5MTctNDcyMC1iZWI3LTFhYzVkMWY0OWQ5NSIsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJ1c2VyIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJvcGVuaWQgZW1haWwgcHJvZmlsZSJ9.6BVpoZCsZbb6vPpdFwspAFT8lYCLYyNrcrOU-27VMaY", + id_token: "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJGSjg2R2NGM2pUYk5MT2NvNE52WmtVQ0lVbWZZQ3FvcXRPUWVNZmJoTmxFIn0.eyJqdGkiOiIzNjMxZTZlNi03MTQ1LTQyZWUtOWU2Yi01MDFkNDFhZGI1NGYiLCJleHAiOjE1ODAxMjYyMjEsIm5iZiI6MCwiaWF0IjoxNTgwMTI1OTIxLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODEvYXV0aC9yZWFsbXMvZXhhbXBsZSIsImF1ZCI6ImpzLWNvbnNvbGUiLCJzdWIiOiI2N2MzMzEzNC1hYWExLTRkODgtYTdjZS0zNTQwOGQwZjEzMzIiLCJ0eXAiOiJJRCIsImF6cCI6ImpzLWNvbnNvbGUiLCJub25jZSI6ImJmMmY4MDY5LTJhM2YtNDNjYS05YjZjLWQ5OTY3MTgwNmY1NiIsImF1dGhfdGltZSI6MTU4MDEyNTkyMSwic2Vzc2lvbl9zdGF0ZSI6IjY3ZTZhZmM1LTc5MTctNDcyMC1iZWI3LTFhYzVkMWY0OWQ5NSIsImFjciI6IjEiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJTYW1wbGUgVXNlciIsInByZWZlcnJlZF91c2VybmFtZSI6InVzZXIiLCJnaXZlbl9uYW1lIjoiU2FtcGxlIiwiZmFtaWx5X25hbWUiOiJVc2VyIiwiZW1haWwiOiJzYW1wbGUtdXNlckBleGFtcGxlIn0.pDHa-ioVBiHNRHiu0atnKTNHn2d_NPMFYBoiQXTuZ4Wj0jfwUqsOD1KIC1t5Q1-OBNLjnzBRhm8qfvg3Vm-B7mNchIJkGOJlF8XcN7e1VyXOWb2yNvZ4TL5QtF_5aVx-_WgpajiUdQyKVEWtwMbb1qyKMVHH2vIxtzep9Sy2zek", + account: { + username: "user", + firstName: "Sample", + lastName: "User", + email: "sample-user@example", + emailVerified: false, + attributes: {} + } + } + }, "index.html"); + cy.url().should("be.equal", `${Cypress.config("baseUrl")}/index.html`); + cy.get("#output").should("contain.text", "Init Success (Authenticated)"); + }); +}); + diff --git a/cypress/integration/login.spec.ts b/cypress/integration/login.spec.ts index 95a3452..597e564 100644 --- a/cypress/integration/login.spec.ts +++ b/cypress/integration/login.spec.ts @@ -57,3 +57,63 @@ describe("Keycloak Login", () => { }); }); }); + +describe("Keycloak Login with runtime credentials", () => { + beforeEach(() => { + cy.kcLogout(); + cy.kcLogin({ + username: "user", + password: "password" + }).as("tokens"); + cy.visit(""); + }); + + it("should show user as authenticated", () => { + cy.get("#output").should("contain.text", "Init Success (Authenticated)"); + }); + + it("should have saved accessToken", () => { + cy.get("#output").should("contain.text", "Init Success (Authenticated)"); + + cy.get("@tokens").should(tokens => { + expect(tokens) + .to.have.property("access_token") + .to.have.length.greaterThan(0); + + expect(tokens) + .to.have.property("id_token") + .to.have.length.greaterThan(0); + + expect(tokens) + .to.have.property("refresh_token") + .to.have.length.greaterThan(0); + }); + }); + + it("should refresh tokens correctly", () => { + cy.server(); + cy.route("post", "**/protocol/openid-connect/token").as("tokenRoute"); + + cy.get("#output").should("contain.text", "Init Success (Authenticated)"); + + cy.findByText("Refresh Token").click(); + + cy.wait("@tokenRoute").then(xhr => { + expect(xhr.status).to.be.equal(200); + + const body = xhr.responseBody; + + expect(body) + .to.have.property("access_token") + .to.have.length.greaterThan(0); + + expect(body) + .to.have.property("id_token") + .to.have.length.greaterThan(0); + + expect(body) + .to.have.property("refresh_token") + .to.have.length.greaterThan(0); + }); + }); +}); diff --git a/index.d.ts b/index.d.ts index 407719e..c75d730 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,8 +1,8 @@ /// interface UserData { - username: string; - password: string; + username?: string; + password?: string; fakeLogin?: { access_token: string; refresh_token: string; @@ -20,8 +20,8 @@ interface KcTokens { // eslint-disable-next-line no-unused-vars declare namespace Cypress { interface Chainable { - kcLogin(user: string): Chainable; + kcLogin(user: string | UserData): Chainable; kcLogout(): Chainable; - kcFakeLogin(user: string, visitUrl?: string): Chainable; + kcFakeLogin(user: string | UserData, visitUrl?: string): Chainable; } } diff --git a/package-lock.json b/package-lock.json index b084a11..3be3031 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2098,9 +2098,9 @@ } }, "acorn": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", - "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz", + "integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==", "dev": true }, "acorn-jsx": { @@ -14087,9 +14087,9 @@ }, "dependencies": { "acorn": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz", - "integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", + "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", "dev": true }, "braces": { diff --git a/package.json b/package.json index f369cbc..e4d30a0 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "cypress-keycloak-commands", + "name": "@svalabs/cypress-keycloak-commands", "version": "0.1.0", "description": "Cypress commands for login with Keycloak", "main": "dist/index.js", @@ -19,7 +19,7 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/Fredx87/cypress-keycloak-commands.git" + "url": "git+https://github.com/svalabs/cypress-keycloak-commands.git" }, "keywords": [ "cypress", @@ -32,9 +32,9 @@ "author": "Gianluca Frediani ", "license": "MIT", "bugs": { - "url": "https://github.com/Fredx87/cypress-keycloak-commands/issues" + "url": "https://github.com/svalabs/cypress-keycloak-commands/issues" }, - "homepage": "https://github.com/Fredx87/cypress-keycloak-commands#readme", + "homepage": "https://github.com/svalabs/cypress-keycloak-commands#readme", "dependencies": {}, "devDependencies": { "@cypress/webpack-preprocessor": "^4.1.1", @@ -67,5 +67,8 @@ "*.{ts,tsx,js}": [ "eslint --fix" ] + }, + "publishConfig": { + "access": "public" } } diff --git a/src/kc-fake-login.ts b/src/kc-fake-login.ts index 0ca7254..67641da 100644 --- a/src/kc-fake-login.ts +++ b/src/kc-fake-login.ts @@ -1,9 +1,16 @@ import { createUUID, decodeToken } from "./utils"; -Cypress.Commands.add("kcFakeLogin", (user: string, visitUrl = "") => { +Cypress.Commands.add("kcFakeLogin", (user: string | UserData, visitUrl = "") => { Cypress.log({ name: "Fake Login" }); - return cy.fixture(`users/${user}`).then((userData: UserData) => { + let userDataChainable: Cypress.Chainable; + if (typeof user === 'string') { + userDataChainable = cy.fixture(`users/${user}`); + } else { + userDataChainable = cy.wrap(user, {log: false}); + } + + return userDataChainable.then((userData: UserData) => { if (!userData.fakeLogin) { throw new Error( "To use kcFakeLogin command you should define fakeLogin data in fixture" diff --git a/src/kc-login.ts b/src/kc-login.ts index 0ba4aa9..8556d5d 100644 --- a/src/kc-login.ts +++ b/src/kc-login.ts @@ -1,9 +1,27 @@ import { getAuthCodeFromLocation } from "./utils"; -Cypress.Commands.add("kcLogin", (user: string) => { +Cypress.Commands.add("kcLogin", (user: string | UserData) => { Cypress.log({ name: "Login" }); - cy.fixture(`users/${user}`).then((userData: UserData) => { + let userDataChainable: Cypress.Chainable; + if (typeof user === 'string') { + userDataChainable = cy.fixture(`users/${user}`); + } else { + userDataChainable = cy.wrap(user, {log: false}); + } + + userDataChainable.then((userData: UserData) => { + if (!userData.username) { + throw new Error( + "To use kcLogin command, you should define a 'username' field in your User data" + ); + } + if (!userData.password) { + throw new Error( + "To use kcLogin command, you should define a 'password' field in your User data" + ); + } + const authBaseUrl = Cypress.env("auth_base_url"); const realm = Cypress.env("auth_realm"); const client_id = Cypress.env("auth_client_id");