How to Test SeaText Cross‑Origin Behavior Before Deploying to All SPA Domains
Add staging domains to SeaText's allowedOrigins list, deploy to a preview environment, and run automated Cypress or Playwright tests that verify the script loads, translates content, and shows no CORS errors. Then promote to...
Add staging domains to SeaText's allowedOrigins list, deploy to a preview environment, and run automated Cypress/Playwright tests that verify the script loads and translates without CORS errors. Then promote to production once all tests pass.
What is cross‑origin testing for SeaText?
Cross‑origin testing confirms that the SeaText script can be loaded and that its API calls succeed from each domain your SPA uses. Browsers enforce the Same‑Origin Policy, so a request from staging.example.com to seatext.com will be blocked unless SeaText returns the proper Access‑Control‑Allow‑Origin header.
Prerequisites
- Access to the SeaText dashboard to edit
allowedOrigins. - A preview or staging deployment that mirrors your production SPA.
- Cypress or Playwright installed in your CI pipeline.
- Knowledge of your SPA’s build commands (e.g.,
npm run build,ng serve).
Why cross‑origin testing matters before production
The Same‑Origin Policy protects users by preventing a page from reading data from a different origin without explicit permission. SeaText uses CORS headers to grant that permission. If the header is missing or mismatched, the browser blocks the request and you see errors such as:
Access to fetch at 'https://api.seatext.com/translate' from origin 'https://staging.example.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
These errors stop translation, break dynamic headline rewriting, and can cause a poor user experience. Testing before production ensures that every staging sub‑domain is correctly listed in allowedOrigins, that preflight OPTIONS requests succeed, and that your SPA does not encounter silent failures in the field.
Step 1: Configure allowedOrigins for staging
- Log in to the SeaText dashboard and open the domain settings page.
- Add each staging sub‑domain (e.g.,
staging.example.com,preview.example.com) to theallowedOriginslist. - Save the changes. Propagation typically takes a few minutes.
Why this step matters: Without the origin in the whitelist, the browser will block the script’s fetch calls, resulting in the CORS error shown above. Adding the origin tells SeaText’s CDN to include the correct header in every response.
Step 2: Deploy to a preview environment
- Run the standard build command for your framework (e.g.,
npm run buildfor React,ng buildfor Angular,npm run buildfor Vue). - Deploy the generated assets to your preview URL.
- Open the page in a browser and verify that the SeaText snippet (containing
SEATEXTCODEINTEGRATION) appears in the<body>tag.
Why this step matters: The snippet is loaded asynchronously (as documented in the SeaText integration guide) which helps page‑load performance. If the snippet is missing or placed incorrectly, the script never runs and no translation occurs.
Step 3: Write automated tests
Both Cypress and Playwright can capture console errors, inspect network responses, and assert that translation occurs.
Cypress example
/// <reference types="cypress" />
const origins = [
'https://staging.example.com',
'https://preview.example.com'
];
origins.forEach(origin => {
it(`checks SeaText on ${origin}`, () => {
cy.visit(origin);
// Capture console errors
cy.on('window:before:load', win => {
win.console.error = cy.stub().as('consoleError');
});
// Wait for the SeaText script to load
cy.get('script[src*="seatext"]', { timeout: 10000 }).should('exist');
// Assert no CORS errors
cy.get('@consoleError').should('not.be.calledWithMatch', /CORS/);
// Verify at least one element is translated
cy.get('[data-seatext-translated]', { timeout: 5000 })
.first()
.should('contain.text', /./);
});
});
Playwright example
import { test, expect } from '@playwright/test';
const origins = [
'https://staging.example.com',
'https://preview.example.com'
];
for (const origin of origins) {
test(`SeaText works on ${origin}`, async ({ page }) => {
const messages: string[] = [];
page.on('console', msg => messages.push(msg.text()));
await page.goto(origin);
// Ensure script tag is present
await expect(page.locator('script[src*="seatext"]')).toHaveCount(1);
// Look for CORS errors in console output
const corsErrors = messages.filter(m => /CORS/.test(m));
expect(corsErrors).toHaveLength(0);
// Check translation of a known element
const translated = await page.locator('[data-seatext-translated]').first().innerText();
expect(translated).not.toBe('');
});
}
Why this step matters: Automated tests catch missing origins, mis‑typed domain names, and network‑level failures before any real user sees the problem.
Step 4: Run tests and verify no CORS errors
- Execute the test suite against the preview URLs (e.g.,
npm run test:ci). - If any test fails, return to Step 1 and add the missing origin.
- When all tests pass, you have confidence that the script loads, the API calls succeed, and translation appears.
What to look for in DevTools: In the Console tab, CORS errors appear as red messages containing “blocked by CORS policy”. In the Network tab, a preflight OPTIONS request should return 200 with an Access-Control-Allow-Origin header matching your staging domain.
Step 5: Promote to production
- Merge the preview branch into the main branch.
- Run the production build (
npm run buildorng build --prod). - Deploy to the live domain.
- Run a quick smoke test (manual or automated) to confirm translation works on the live site.
Why this step matters: Production often uses a different domain (e.g., www.example.com). Add that domain to allowedOrigins before the final smoke test.
Step 6: Post‑deployment monitoring
- Watch the SeaText dashboard for new origin warnings.
- Schedule nightly CI runs that repeat the Cypress/Playwright suite against production.
- Update
allowedOriginswhenever you add a new sub‑domain, custom domain, or CDN edge.
Why ongoing monitoring matters: CORS headers are cached at CDN edges. A new edge node may need a few minutes to receive the updated whitelist. Continuous checks catch propagation delays.
Limitations and troubleshooting
- Async loading: The SeaText snippet includes the
asyncattribute. If you manually move the script or adddefer, ensure the script still loads before your SPA renders translation‑dependent elements. - Local storage permissions: SeaText stores an identifier in
localStorage. Browsers in private mode or with strict storage policies may block this. Verify thatlocalStorage.setItemdoes not throw errors in the console. - Network inspection: In DevTools, filter by
seatext.com. A successful request returns200and includesAccess-Control-Allow-Origin: https://staging.example.com. A403or missing header indicates an origin mismatch. - Framework‑specific quirks:
- React: Ensure the snippet is placed outside the root
div#rootso React’s virtual DOM does not overwrite it during hot reloads. - Vue: Add the snippet in
public/index.htmlbefore the Vue app mounts. - Angular: Insert the snippet in
src/index.htmland verify that Angular’sng servedoes not strip the async attribute.
- React: Ensure the snippet is placed outside the root
- Build‑time vs runtime: The snippet runs at runtime. If you pre‑render pages (e.g., using Next.js static export), the script still executes in the browser, but you must ensure the generated HTML includes the snippet.
If you encounter a CORS error only in production, double‑check that the production domain is listed in allowedOrigins and that any edge proxy (Cloudflare, Fastly) is not removing the Access-Control-Allow-Origin header.
Key facts
| Fact | Description |
|---|---|
| Asynchronous loading | The snippet includes the async attribute for the script tag, ensuring that the SeaText AI script loads asynchronously and does not block page rendering. |
| Local storage usage | The script stores an ID in localStorage. Your SPA must allow read/write access to local storage for the script to function correctly. |
| Cross‑origin considerations | SeaText requires each SPA domain to be listed in allowedOrigins to avoid Same‑Origin Policy blocks. |
| Build and serve | Build and serve your application using the standard commands for your framework (npm start, npm run serve, or ng serve). |
| Inspect the page | Open browser Developer Tools (F12) and check the Console and Network tabs to verify that the SeaText script loads without errors. |
| Functionality check | Ensure that SeaText features, such as translation or dynamic headline rewriting, are working as expected within your SPA. |
FAQ
- Why add staging domains to
allowedOrigins? SeaText blocks requests from origins not on the whitelist to prevent unauthorized usage. - Can I reuse the same test script for multiple domains? Yes. Parameterize the script with an array of URLs and loop through them.
- What does a CORS error look like in the console? It mentions “blocked by CORS policy” and shows the missing
Access-Control-Allow-Originheader. - What if I see a CORS error only in production? Verify that the production domain is in
allowedOriginsand that no proxy strips the header. - How often should I update
allowedOrigins? Whenever you add a new sub‑domain, custom domain, or preview URL that will load SeaText. - Do I need to disable the async attribute for testing? No. Async loading does not affect CORS behavior and should remain enabled for performance.
- How can I confirm that translation actually occurred? Look for elements with the attribute
data-seatext-translatedor check that visible text changes to the target language. - What preflight request should I expect? An
OPTIONSrequest tohttps://api.seatext.comthat returns200with the correctAccess-Control-Allow-Originheader.
Terminology
- CORS – Cross‑Origin Resource Sharing, a browser mechanism that restricts cross‑origin HTTP requests unless the server sends appropriate headers.
- allowedOrigins – SeaText setting that lists domains permitted to load the script and call its APIs.
- preview environment – A staging deployment that mirrors production but is not exposed to end users.
- preflight request – An
OPTIONSrequest browsers send to verify CORS permissions before the actual request. - async attribute – An HTML attribute that tells the browser to download and execute the script without blocking page parsing.
Further reading
- OWASP – Testing Cross Origin Resource Sharing
- Microsoft – Enable CORS in ASP.NET Core
- Microsoft – Enabling CORS in ASP.NET Web API
Further reading and comparison sources
These external sources provide additional context for evaluating the topic. Their inclusion is not an endorsement.
Learn more
Visit the website for more information.