379 lines
10 KiB
Markdown
379 lines
10 KiB
Markdown
|
|
# Working Around Iframe Testing Limitations
|
||
|
|
|
||
|
|
## Problem Statement
|
||
|
|
|
||
|
|
The H5 application uses an iframe-based wrapper (`/static/html/pc.html`) which prevents automated browser testing tools from interacting with the actual application content. The iframe loads the mobile app at `/` inside it, creating an isolated browsing context.
|
||
|
|
|
||
|
|
## Architecture Diagram
|
||
|
|
|
||
|
|
```
|
||
|
|
┌─────────────────────────────────────────┐
|
||
|
|
│ http://localhost:8080/static/html/pc.html │
|
||
|
|
│ ┌─────────────────────────────────────┐ │
|
||
|
|
│ │ <iframe src="/"> │ │
|
||
|
|
│ │ ┌───────────────────────────────┐ │ │
|
||
|
|
│ │ │ Actual H5 App │ │ │
|
||
|
|
│ │ │ (慢生活营养专家) │ │ │
|
||
|
|
│ │ │ │ │ │
|
||
|
|
│ │ │ - User Card │ │ │
|
||
|
|
│ │ │ - Function Cards │ │ │
|
||
|
|
│ │ │ - Navigation │ │ │
|
||
|
|
│ │ └───────────────────────────────┘ │ │
|
||
|
|
│ └─────────────────────────────────────┘ │
|
||
|
|
└─────────────────────────────────────────┘
|
||
|
|
|
||
|
|
Browser Tools CAN access: PC wrapper (outer page)
|
||
|
|
Browser Tools CANNOT access: Iframe content (actual app)
|
||
|
|
```
|
||
|
|
|
||
|
|
## Why This Happens
|
||
|
|
|
||
|
|
From `/msh_single_uniapp/static/html/pc.html`:
|
||
|
|
```html
|
||
|
|
<iframe src="/" id="iframe"></iframe>
|
||
|
|
```
|
||
|
|
|
||
|
|
The pc.html wrapper:
|
||
|
|
1. Detects screen width
|
||
|
|
2. If width > 450px: Shows centered iframe with border (PC view)
|
||
|
|
3. If width ≤ 420px: Redirects to `/` (but still loads through router)
|
||
|
|
4. Sets `window.isPC = true` flag
|
||
|
|
|
||
|
|
## Current Limitations
|
||
|
|
|
||
|
|
### What Works ✅
|
||
|
|
- Page navigation (can change URL)
|
||
|
|
- Screenshot capture (visual verification)
|
||
|
|
- Network monitoring (API calls visible)
|
||
|
|
- Console log reading (errors visible)
|
||
|
|
- Page load timing
|
||
|
|
|
||
|
|
### What Doesn't Work ❌
|
||
|
|
- Element clicking (no refs inside iframe)
|
||
|
|
- Form input (no access to input fields)
|
||
|
|
- Text selection (isolated context)
|
||
|
|
- Element attribute reading (no refs)
|
||
|
|
- Hover interactions
|
||
|
|
|
||
|
|
## Solutions & Workarounds
|
||
|
|
|
||
|
|
### Solution 1: Manual Testing (Current Approach)
|
||
|
|
**Status:** ✅ Implemented
|
||
|
|
|
||
|
|
Use the comprehensive manual testing checklist:
|
||
|
|
- `/docs/Testing/manual-testing-checklist.md`
|
||
|
|
|
||
|
|
**Pros:**
|
||
|
|
- Works immediately
|
||
|
|
- No code changes required
|
||
|
|
- Can test all features
|
||
|
|
- Human verification of UX
|
||
|
|
|
||
|
|
**Cons:**
|
||
|
|
- Time-consuming
|
||
|
|
- Not reproducible
|
||
|
|
- Human error possible
|
||
|
|
- Cannot automate regression tests
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Solution 2: Direct H5 Access (Dev Environment)
|
||
|
|
**Status:** 🔶 Recommended for Testing
|
||
|
|
|
||
|
|
**Step A: Modify pc.html for Testing**
|
||
|
|
|
||
|
|
Create a test version that bypasses iframe:
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
// Add to pc.html temporarily
|
||
|
|
if (window.location.search.includes('direct=true')) {
|
||
|
|
window.location.href = '/';
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
Then access: `http://localhost:8080/static/html/pc.html?direct=true`
|
||
|
|
|
||
|
|
**Step B: Access Root Directly with Mobile User-Agent**
|
||
|
|
|
||
|
|
The app routing logic checks for mobile devices. Browser tools can spoof user-agent:
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
// In browser console before navigation:
|
||
|
|
Object.defineProperty(navigator, 'userAgent', {
|
||
|
|
get: function () {
|
||
|
|
return 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X)';
|
||
|
|
}
|
||
|
|
});
|
||
|
|
```
|
||
|
|
|
||
|
|
Then navigate to `http://localhost:8080/`
|
||
|
|
|
||
|
|
**Step C: Modify Vue Router for Test Mode**
|
||
|
|
|
||
|
|
Add a query parameter to bypass PC detection:
|
||
|
|
|
||
|
|
In your router configuration or App.vue:
|
||
|
|
```javascript
|
||
|
|
// If ?test=true in URL, don't redirect to pc.html
|
||
|
|
if (this.$route.query.test === 'true') {
|
||
|
|
// Stay on current page
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
Access: `http://localhost:8080/?test=true`
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Solution 3: E2E Framework with Iframe Support
|
||
|
|
**Status:** 📋 Future Implementation
|
||
|
|
|
||
|
|
#### Option A: Playwright
|
||
|
|
```javascript
|
||
|
|
// Playwright can switch to iframe context
|
||
|
|
const page = await browser.newPage();
|
||
|
|
await page.goto('http://localhost:8080');
|
||
|
|
|
||
|
|
// Switch to iframe
|
||
|
|
const iframe = page.frameLocator('#iframe');
|
||
|
|
await iframe.locator('.login-button').click();
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Option B: Cypress with iframe plugin
|
||
|
|
```javascript
|
||
|
|
// Install: npm install -D cypress-iframe
|
||
|
|
cy.visit('http://localhost:8080');
|
||
|
|
cy.frameLoaded('#iframe');
|
||
|
|
cy.iframe().find('.login-button').click();
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Option C: Puppeteer
|
||
|
|
```javascript
|
||
|
|
const page = await browser.newPage();
|
||
|
|
await page.goto('http://localhost:8080');
|
||
|
|
|
||
|
|
// Get iframe
|
||
|
|
const frameHandle = await page.$('#iframe');
|
||
|
|
const frame = await frameHandle.contentFrame();
|
||
|
|
await frame.click('.login-button');
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Solution 4: Remove Iframe Wrapper (Architecture Change)
|
||
|
|
**Status:** 🎯 Long-term Recommendation
|
||
|
|
|
||
|
|
**Current Architecture:**
|
||
|
|
```
|
||
|
|
User → localhost:8080 → pc.html (checks screen size) → iframe src="/"
|
||
|
|
↓
|
||
|
|
Actual H5 App
|
||
|
|
```
|
||
|
|
|
||
|
|
**Proposed Architecture:**
|
||
|
|
```
|
||
|
|
User → localhost:8080 → Direct H5 App
|
||
|
|
(CSS media queries handle responsive design)
|
||
|
|
```
|
||
|
|
|
||
|
|
**Benefits:**
|
||
|
|
- ✅ Enables automated testing
|
||
|
|
- ✅ Better performance (no iframe overhead)
|
||
|
|
- ✅ Simpler architecture
|
||
|
|
- ✅ Better SEO
|
||
|
|
- ✅ Easier debugging
|
||
|
|
|
||
|
|
**Changes Required:**
|
||
|
|
|
||
|
|
1. **Remove pc.html wrapper**
|
||
|
|
2. **Use CSS media queries for responsive design:**
|
||
|
|
```css
|
||
|
|
/* Instead of iframe with fixed size */
|
||
|
|
@media screen and (min-width: 450px) {
|
||
|
|
.mobile-app {
|
||
|
|
max-width: 375px;
|
||
|
|
margin: 0 auto;
|
||
|
|
border: 1px solid #f5f5f5;
|
||
|
|
border-radius: 4px;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
3. **Update build configuration:**
|
||
|
|
```javascript
|
||
|
|
// In vue.config.js or similar
|
||
|
|
publicPath: '/',
|
||
|
|
// Remove redirect logic
|
||
|
|
```
|
||
|
|
|
||
|
|
**Implementation Estimate:** 2-4 hours
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Recommended Testing Strategy
|
||
|
|
|
||
|
|
### Phase 1: Current (Manual Testing)
|
||
|
|
- Use manual testing checklist
|
||
|
|
- Document all findings
|
||
|
|
- Capture screenshots
|
||
|
|
- ~2-3 hours of testing
|
||
|
|
|
||
|
|
### Phase 2: Quick Win (Direct Access)
|
||
|
|
- Implement Solution 2 (query parameter bypass)
|
||
|
|
- Enable automated testing for critical paths
|
||
|
|
- ~1 hour implementation
|
||
|
|
- Saves ~10 hours/week in testing
|
||
|
|
|
||
|
|
### Phase 3: Proper Tooling (E2E Framework)
|
||
|
|
- Set up Playwright or Cypress with iframe support
|
||
|
|
- Create automated test suite
|
||
|
|
- ~1 week implementation
|
||
|
|
- Full regression coverage
|
||
|
|
|
||
|
|
### Phase 4: Architecture Improvement (Remove Iframe)
|
||
|
|
- Refactor to remove iframe wrapper
|
||
|
|
- Use responsive CSS instead
|
||
|
|
- ~1 day implementation
|
||
|
|
- Permanent fix, enables all testing tools
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Temporary Testing Script
|
||
|
|
|
||
|
|
For immediate testing needs, create this script:
|
||
|
|
|
||
|
|
**File:** `test-helpers/direct-access.js`
|
||
|
|
```javascript
|
||
|
|
// Run this in browser console to enable direct testing
|
||
|
|
(function() {
|
||
|
|
// Method 1: Remove iframe and show content directly
|
||
|
|
const iframe = document.getElementById('iframe');
|
||
|
|
if (iframe) {
|
||
|
|
const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
|
||
|
|
document.body.innerHTML = iframeDoc.body.innerHTML;
|
||
|
|
|
||
|
|
// Copy styles
|
||
|
|
const iframeStyles = iframeDoc.getElementsByTagName('style');
|
||
|
|
for (let style of iframeStyles) {
|
||
|
|
document.head.appendChild(style.cloneNode(true));
|
||
|
|
}
|
||
|
|
|
||
|
|
console.log('✅ Iframe content extracted. You can now test directly.');
|
||
|
|
}
|
||
|
|
|
||
|
|
// Method 2: Add test hooks
|
||
|
|
window.testMode = true;
|
||
|
|
window.getIframeDoc = () => {
|
||
|
|
return iframe.contentDocument || iframe.contentWindow.document;
|
||
|
|
};
|
||
|
|
|
||
|
|
console.log('✅ Test helpers loaded. Use window.getIframeDoc() to access iframe.');
|
||
|
|
})();
|
||
|
|
```
|
||
|
|
|
||
|
|
**Usage:**
|
||
|
|
1. Open browser DevTools
|
||
|
|
2. Paste script in console
|
||
|
|
3. Press Enter
|
||
|
|
4. Content now accessible for testing
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Testing Without Iframe Access
|
||
|
|
|
||
|
|
### Approach 1: API Testing
|
||
|
|
Since network requests are visible, test APIs directly:
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
// Test login API
|
||
|
|
fetch('http://127.0.0.1:20822/api/front/login/mobile', {
|
||
|
|
method: 'POST',
|
||
|
|
headers: {
|
||
|
|
'Content-Type': 'application/json'
|
||
|
|
},
|
||
|
|
body: JSON.stringify({
|
||
|
|
phone: '18621813282',
|
||
|
|
password: 'A123456'
|
||
|
|
})
|
||
|
|
})
|
||
|
|
.then(r => r.json())
|
||
|
|
.then(console.log);
|
||
|
|
```
|
||
|
|
|
||
|
|
### Approach 2: Visual Testing
|
||
|
|
Use screenshot comparison tools:
|
||
|
|
1. Take screenshot of expected state
|
||
|
|
2. Take screenshot after changes
|
||
|
|
3. Compare images using tools like:
|
||
|
|
- pixelmatch
|
||
|
|
- looks-same
|
||
|
|
- BackstopJS
|
||
|
|
|
||
|
|
### Approach 3: Network Monitoring
|
||
|
|
Verify functionality by monitoring network calls:
|
||
|
|
1. User clicks button
|
||
|
|
2. Check if correct API called
|
||
|
|
3. Verify response
|
||
|
|
4. Check if UI updates (via screenshot)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Implementation Priority
|
||
|
|
|
||
|
|
### High Priority (This Week)
|
||
|
|
1. ✅ Complete manual testing
|
||
|
|
2. ⏳ Fix known configuration issue
|
||
|
|
3. ⏳ Document manual test results
|
||
|
|
|
||
|
|
### Medium Priority (This Month)
|
||
|
|
1. 📋 Implement Solution 2 (direct access for testing)
|
||
|
|
2. 📋 Set up API testing suite
|
||
|
|
3. 📋 Visual regression testing setup
|
||
|
|
|
||
|
|
### Low Priority (This Quarter)
|
||
|
|
1. 📋 Evaluate E2E framework (Playwright vs Cypress)
|
||
|
|
2. 📋 Consider architecture refactoring
|
||
|
|
3. 📋 Implement automated test suite
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Questions & Answers
|
||
|
|
|
||
|
|
**Q: Why does the app use an iframe?**
|
||
|
|
A: To provide a centered mobile view on desktop browsers while maintaining the mobile H5 codebase. It's a common pattern for mobile-first apps.
|
||
|
|
|
||
|
|
**Q: Can I just disable the iframe?**
|
||
|
|
A: Yes, but it requires code changes. See Solution 4 above.
|
||
|
|
|
||
|
|
**Q: Will removing the iframe break anything?**
|
||
|
|
A: No, if done properly. The iframe is just a container. The app logic is independent.
|
||
|
|
|
||
|
|
**Q: What's the fastest way to enable automated testing?**
|
||
|
|
A: Implement Solution 2 (query parameter to bypass iframe). Takes ~1 hour, enables all browser testing tools.
|
||
|
|
|
||
|
|
**Q: Should we always use iframes?**
|
||
|
|
A: No. Modern responsive design with CSS media queries is preferred. Iframes add complexity and testing difficulty.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Resources
|
||
|
|
|
||
|
|
### Documentation
|
||
|
|
- [MDN: Working with iframes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe)
|
||
|
|
- [Playwright: Frames](https://playwright.dev/docs/frames)
|
||
|
|
- [Cypress: Iframes](https://docs.cypress.io/api/commands/its#Iframe-Support)
|
||
|
|
|
||
|
|
### Tools
|
||
|
|
- [cypress-iframe plugin](https://github.com/kgroat/cypress-iframe)
|
||
|
|
- [Playwright](https://playwright.dev/)
|
||
|
|
- [Puppeteer](https://pptr.dev/)
|
||
|
|
|
||
|
|
### Testing Strategies
|
||
|
|
- [Testing Best Practices](https://kentcdodds.com/blog/common-mistakes-with-react-testing-library)
|
||
|
|
- [Visual Regression Testing](https://percy.io/visual-testing)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
**Last Updated:** March 2, 2026
|
||
|
|
**Status:** Documented
|
||
|
|
**Recommended Action:** Implement Solution 2 for immediate testing needs
|