-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add basic Cypress e2e test * Deploy to CI/CD Github Actions * Update main.yml * Update main.yml * Update main.yml * Update main.yml * Update main.yml * Add basic spec * Adjust management key naming * Add UI and programmatic login * Add api form validation check * Remove UI Test steps * Remove UI test * Update README.md
- Loading branch information
1 parent
c5c44d5
commit df3e5f1
Showing
11 changed files
with
2,954 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
name: Cypress Tests | ||
on: [push] | ||
jobs: | ||
cypress-run: | ||
name: E2E Tests | ||
runs-on: ubuntu-latest | ||
env: | ||
NEXT_PUBLIC_DESCOPE_PROJECT_ID: ${{ vars.NEXT_PUBLIC_DESCOPE_PROJECT_ID }} | ||
DESCOPE_MANAGEMENT_KEY: ${{ secrets.DESCOPE_MANAGEMENT_KEY }} | ||
|
||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v3 | ||
|
||
- name: Install dependencies | ||
run: npm install | ||
|
||
- name: Cypress run | ||
uses: cypress-io/github-action@v5 | ||
with: | ||
start: npm run dev | ||
wait-on: 'http://localhost:3000' | ||
wait-on-timeout: 120 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,6 +27,7 @@ yarn-error.log* | |
|
||
# local env files | ||
.env*.local | ||
.env | ||
|
||
# vercel | ||
.vercel | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { defineConfig } from "cypress"; | ||
|
||
import * as dotenv from 'dotenv'; | ||
dotenv.config(); | ||
|
||
export default defineConfig({ | ||
|
||
e2e: { | ||
includeShadowDom: true, // Important for interacting with Descope components | ||
baseUrl: 'http://localhost:3000', | ||
setupNodeEvents(on, config) { | ||
// implement node event listeners here | ||
}, | ||
}, | ||
env: { | ||
descope_project_id: process.env.NEXT_PUBLIC_DESCOPE_PROJECT_ID, | ||
descope_management_key: process.env.DESCOPE_MANAGEMENT_KEY | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
describe('Descope', function () { | ||
beforeEach(function () { | ||
cy.deleteAllTestUsers() | ||
cy.loginViaDescopeAPI() | ||
}) | ||
|
||
it('shows test user welcome message', function () { | ||
cy.contains('Hello Test User').should('be.visible') | ||
}) | ||
|
||
it('validates api request', function () { | ||
cy.get('[data-cy=api-form-button]').click() | ||
cy.contains('Result: Request Validated').should('be.visible'); | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"name": "Using fixtures to represent data", | ||
"email": "hello@cypress.io", | ||
"body": "Fixtures are a great way to mock data for responses to routes" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
/// <reference types="cypress" /> | ||
// *********************************************** | ||
|
||
const projectId = Cypress.env('descope_project_id') | ||
const managementKey = Cypress.env('descope_management_key') | ||
const descopeAPIDomain = "api.descope.com" | ||
|
||
|
||
|
||
// Define the authorization header | ||
const authHeader = { | ||
'Authorization': `Bearer ${projectId}:${managementKey}`, | ||
} | ||
|
||
// Define the base URL for Descope API | ||
const descopeApiBaseURL = `https://${descopeAPIDomain}/v1`; | ||
|
||
const testUserLoginId = "testUser" + Math.floor(1000 + Math.random() * 9000) + "@gmail.com"; // Must match email to pass validation | ||
|
||
// Define the test user details | ||
const testUser = { | ||
loginId: testUserLoginId, | ||
email: testUserLoginId, | ||
phone: "+11231231234", | ||
verifiedEmail: true, | ||
verifiedPhone: true, | ||
displayName: "Test User", | ||
test: true, | ||
} | ||
declare namespace Cypress { | ||
interface Chainable<Subject = any> { | ||
loginViaDescopeUI(): Chainable<any>; | ||
deleteAllTestUsers(): Chainable<any>; | ||
loginViaDescopeAPI(): Chainable<any>; | ||
} | ||
} | ||
// Add the loginViaDescopeUI command | ||
Cypress.Commands.add('loginViaDescopeUI', () => { | ||
cy.request({ | ||
method: 'POST', | ||
url: `${descopeApiBaseURL}/mgmt/user/create`, | ||
headers: authHeader, | ||
body: testUser, | ||
}) | ||
.then(({ body }) => { | ||
const loginId = body["user"]["loginIds"][0]; | ||
cy.request({ | ||
method: 'POST', | ||
url: `${descopeApiBaseURL}/mgmt/tests/generate/otp`, | ||
headers: authHeader, | ||
body: { | ||
"loginId": loginId, | ||
"deliveryMethod": "email" | ||
} | ||
}) | ||
.then(({ body }) => { | ||
const otpCode = body["code"] | ||
const loginID = body["loginId"] | ||
cy.visit('/login') | ||
|
||
cy.get('descope-wc') | ||
.find('input') | ||
.type(loginID) | ||
// If you haven't set `includeShadowDom: true` in your config (as recommended above), | ||
// you'll have to use `.shadow()` in each function call. | ||
// So the previous line would look like this: | ||
// cy.get('descope-wc').shadow().find('input').type(loginID) | ||
|
||
cy.get('descope-wc') | ||
.find('button').contains('Continue').click() | ||
cy.get('descope-wc').find('.descope-input-wrapper').find('input').should('exist') // Assertion added to wait for the OTP code input to appear | ||
let otpCodeArray: string[] = Array.from(otpCode); // Convert the OTP code string to an array | ||
for (var i = 0; i < otpCodeArray.length; i++) { | ||
cy.get('descope-wc').find('.descope-input-wrapper').find('input').eq(i + 1).type(otpCodeArray[i], { force: true }) | ||
} | ||
cy.get('descope-wc') | ||
.find('button').contains('Submit').click() | ||
|
||
// Customize these steps based on your authentication flow | ||
cy.get('descope-wc') | ||
.find('button').contains('Submit').click() | ||
}) | ||
}) | ||
}) | ||
// Add the loginViaDescopeAPI command | ||
Cypress.Commands.add('loginViaDescopeAPI', () => { | ||
cy.request({ | ||
method: 'POST', | ||
url: `${descopeApiBaseURL}/mgmt/user/create`, | ||
headers: authHeader, | ||
body: testUser, | ||
}) | ||
.then(({ body }) => { | ||
const loginId = body["user"]["loginIds"][0]; | ||
cy.request({ | ||
method: 'POST', | ||
url: `${descopeApiBaseURL}/mgmt/tests/generate/otp`, | ||
headers: authHeader, | ||
body: { | ||
"loginId": loginId, | ||
"deliveryMethod": "email" | ||
} | ||
}) | ||
.then(({ body }) => { | ||
const otpCode = body["code"] | ||
cy.request({ | ||
method: 'POST', | ||
url: `${descopeApiBaseURL}/auth/otp/verify/email`, | ||
headers: authHeader, | ||
body: { | ||
"loginId": loginId, | ||
"code": otpCode | ||
} | ||
}) | ||
.then(({ body }) => { | ||
const sessionJwt = body["sessionJwt"] | ||
const refreshJwt = body["refreshJwt"] | ||
|
||
/** Default name for the session cookie name / local storage key */ | ||
const SESSION_TOKEN_KEY = 'DS'; | ||
/** Default name for the refresh local storage key */ | ||
const REFRESH_TOKEN_KEY = 'DSR'; | ||
|
||
// // Store the JWT in the browser's local storage. | ||
cy.window().then((win) => { | ||
win.localStorage.setItem(SESSION_TOKEN_KEY, sessionJwt); | ||
win.localStorage.setItem(REFRESH_TOKEN_KEY, refreshJwt); | ||
}); | ||
|
||
// // Now navigate to the root URL of your application. | ||
cy.visit('/') | ||
|
||
}) | ||
}) | ||
}) | ||
}) | ||
|
||
// Add the deleteAllTestUsers command | ||
Cypress.Commands.add('deleteAllTestUsers', () => { | ||
cy.request({ | ||
method: 'DELETE', | ||
url: `${descopeApiBaseURL}/mgmt/user/test/delete/all`, | ||
headers: authHeader, | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// *********************************************************** | ||
// This example support/e2e.ts is processed and | ||
// loaded automatically before your test files. | ||
// | ||
// This is a great place to put global configuration and | ||
// behavior that modifies Cypress. | ||
// | ||
// You can change the location of this file or turn off | ||
// automatically serving support files with the | ||
// 'supportFile' configuration option. | ||
// | ||
// You can read more here: | ||
// https://on.cypress.io/configuration | ||
// *********************************************************** | ||
|
||
// Import commands.js using ES2015 syntax: | ||
import './commands' | ||
|
||
// Alternatively you can use CommonJS syntax: | ||
// require('./commands') |
Oops, something went wrong.
df3e5f1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
next-js-sample-app – ./
next-js-sample-app-git-main-allenzhou.vercel.app
next-js-sample-app-ten.vercel.app
next-js-sample-app-allenzhou.vercel.app
thewatercooler.app
www.thewatercooler.app