Open TomlDev opened 1 week ago
Your goal is to automate testing for the JavaScript injection in iframes (embedded apps) for authentication when using React, and you'd like to trigger these tests with GitHub Actions, especially after a PR merge. Here's a structured approach to implement this:
To solve the cross-origin issue that arises from embedding external pages within iframes and injecting JavaScript, setting up a reverse proxy like Traefik is a great solution. This will allow your embedded app to appear as though it’s coming from the same domain as your main app, thus allowing JavaScript injection.
Traefik Configuration: Configure Traefik to proxy requests to your embedded apps so that the browser treats them as same-origin.
Example Traefik Setup:
services:
traefik:
image: traefik:v2.5
ports:
- "80:80"
- "443:443"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
command:
- "--api.insecure=true"
- "--providers.docker=true"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.le.acme.email=your-email@example.com"
- "--certificatesresolvers.le.acme.storage=/letsencrypt/acme.json"
- "--certificatesresolvers.le.acme.tlschallenge=true"
This proxy will help with bypassing CORS and same-origin policy restrictions during the testing phase.
Each embedded page likely has different credentials, URLs, and login/logout flows. A configuration file per embedded app allows easy updating of the test logic and management. You can use JSON or YAML for these configuration files:
config.json
:{
"embeddedApps": [
{
"name": "App1",
"loginUrl": "https://app1.example.com/login",
"logoutUrl": "https://app1.example.com/logout",
"credentials": {
"username": "testUser",
"password": "testPassword"
},
"scripts": {
"loginScript": "path/to/loginScript.js",
"logoutScript": "path/to/logoutScript.js"
},
"successSelectors": {
"login": "#loggedInElement",
"logout": "#loggedOutElement"
}
},
{
"name": "App2",
"loginUrl": "https://app2.example.com/login",
"logoutUrl": "https://app2.example.com/logout",
"credentials": {
"username": "testUser2",
"password": "testPassword2"
},
"scripts": {
"loginScript": "path/to/loginScript2.js",
"logoutScript": "path/to/logoutScript2.js"
},
"successSelectors": {
"login": ".loginSuccess",
"logout": ".logoutSuccess"
}
}
]
}
This config can be parsed in your tests to dynamically load credentials, URLs, and JavaScript files.
To automate testing, use a headless browser tool like Puppeteer or Playwright. These tools allow you to simulate user interactions, inject scripts, and validate the state of the iframe content. Here’s an outline:
Install Puppeteer:
npm install puppeteer
Automate Login/Logout Test:
const puppeteer = require('puppeteer');
const config = require('./config.json'); // Load the configuration file
(async () => {
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
for (const app of config.embeddedApps) {
await page.goto(app.loginUrl);
// Inject login script
await page.addScriptTag({ path: app.scripts.loginScript });
// Wait for login to succeed (using a success selector)
await page.waitForSelector(app.successSelectors.login);
console.log(`${app.name}: Login successful`);
// Perform the logout process
await page.goto(app.logoutUrl);
await page.addScriptTag({ path: app.scripts.logoutScript });
// Wait for logout to succeed
await page.waitForSelector(app.successSelectors.logout);
console.log(`${app.name}: Logout successful`);
}
await browser.close();
})();
Integrate into GitHub Actions:
Create a .github/workflows/test.yml
file to automate the test when you merge a PR.
name: Embedded App Login/Logout Test
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: '14'
- name: Install dependencies
run: npm install
- name: Run Puppeteer Tests
run: node testEmbeddedApps.js # The Puppeteer script file
To check if the JavaScript injection was successful, use the following approaches:
page.on('response')
to capture and verify API responses that confirm authentication.page.on('response', response => {
if (response.url().includes('login-success-endpoint')) {
console.log('Login API returned success');
}
});
The GitHub Actions workflow is designed to trigger automatically on PR merges into the main branch. This ensures the tests are run each time new changes are introduced, helping to catch issues early.
This solution should give you robust, automated tests that ensure your iframe JavaScript injection is always working correctly.
Currently we have for example the SOGo application embedded as native frame with SSO code injection.
If we keep this instead of implementing a cookie based SSO we need to add tests to check the script injection.
It could be possible to test the component with static HTML code or a proxied SOGo.