fix(deploy): strip the embed parameters by name, and scope the timezone runs to the VA specs
Build / Build-and-ng-test (pull_request) Canceled after 0s
Build / Build-and-test-development (pull_request) Canceled after 0s
Lighthouse Checks / lighthouse (pull_request) Canceled after 1s

The standalone URL dropped every query parameter whose name started with
va_, not just va_parmap; the names are now enumerated, and a later
parameter with that prefix survives (the component spec pins the exact
standalone URL instead of a substring, so the query surviving is the
assertion, not an accident of the runner's own query).

The timezone runs are scoped to the VA specs, the only specs with local
calendar arithmetic, so the blocking job no longer runs the whole suite
twice more.
This commit is contained in:
dc@4gl.io committed 2026-10-28 18:58:26 +00:00
1 parent 00257f9160
commit f7e753863b
4 files changed
+32 -6

No files matched your search

+2 -1
View File
@@ -78,7 +78,8 @@ jobs:
- name: Angular Tests in other timezones
# The VA filter clauses are built from local calendar dates, so a
# UTC-only run cannot see a date that slips a day west of UTC or east of
# it. Both scripts are the same suite under a different TZ.
# it. Only the VA specs carry that property, so both scripts run that
# subset rather than the whole suite a second and third time.
run: |
cd client
npm run test:tz-west
+2 -2
View File
@@ -38,8 +38,8 @@
"compodoc:serve": "compodoc -s --name 'Data Controller Client'",
"lighthouse": "lhci autorun",
"ng": "ng",
"test:tz-west": "TZ=America/New_York npm run test:headless",
"test:tz-east": "TZ=Pacific/Auckland npm run test:headless"
"test:tz-west": "TZ=America/New_York npx ng test --no-watch --no-progress --browsers ChromeHeadlessCI --include='**/va-*.spec.ts'",
"test:tz-east": "TZ=Pacific/Auckland npx ng test --no-watch --no-progress --browsers ChromeHeadlessCI --include='**/va-*.spec.ts'"
},
"private": true,
"dependencies": {
+21 -1
View File
@@ -131,13 +131,25 @@ describe('DeployComponent embed guard', () => {
describe('DeployComponent onNavigateToHome', () => {
const originalEmbed = globals.embed
const originalHref = window.location.href
afterEach(() => {
globals.embed = originalEmbed
history.replaceState(null, '', originalHref)
TestBed.resetTestingModule()
})
it('opens the standalone URL, merging an embed tab into the app URL', () => {
// Karma serves the runner with its own query, so the app URL is set here
// rather than read from window.location: the assertion has to see the
// app's query survive the embed parameters being dropped. The shape is
// the real SAS 9 one - the app's `_program` query in the search part,
// the embed switches in the hash query.
history.replaceState(
null,
'',
'/deploy-tc?_program=/Public/app/dc&_debug=131#/editor?embed=va&va_parmap=A-B'
)
const open = spyOn(window, 'open')
TestBed.configureTestingModule({
declarations: [DeployComponent],
@@ -161,7 +173,9 @@ describe('DeployComponent onNavigateToHome', () => {
fixture.componentInstance.onNavigateToHome()
const opened = open.calls.mostRecent().args[0] as string
expect(opened).toBe(standaloneUrl(window.location.href))
expect(opened).toBe(
window.location.origin + '/deploy-tc?_program=/Public/app/dc&_debug=131'
)
expect(opened).not.toContain('#')
expect(opened).not.toContain('embed=')
})
@@ -203,6 +217,12 @@ describe('standaloneUrl', () => {
).toBe(`${origin}/app`)
})
it('keeps a query parameter that merely starts with va_', () => {
expect(standaloneUrl(`${origin}/app?embed=va&va_rowlimit=100`)).toBe(
`${origin}/app?va_rowlimit=100`
)
})
it('resolves a relative URL against the current origin', () => {
expect(standaloneUrl('/app/#/deploy')).toBe(`${origin}/app/`)
})
+7 -2
View File
@@ -1,21 +1,26 @@
/**
* The URL a Data Controller instance runs at when it is not embedded: the same
* URL, without the parts that make it an embed - the `embed` switch, the
* `va_*` parameters, and the hash route.
* `va_parmap` entries, and the hash route.
*
* The rest of the query is kept. On SAS 9 and Viya the app is addressed
* entirely through it (`/SASJobExecution/?_program=/.../startupservice`), so
* dropping the query would open a blank executor rather than the app, and any
* other parameter the deployment relies on would go the same way.
*
* Only these two parameters are embed parameters. A later parameter that
* happens to start with `va_` belongs to the app, not the embed, so it stays.
*
* Parsing with URL also handles the relative hrefs the adapter can hand back,
* which plain string splicing cannot.
*/
const EMBED_PARAMS = ['embed', 'va_parmap']
export const standaloneUrl = (href: string): string => {
const url = new URL(href, window.location.origin)
url.hash = ''
for (const key of Array.from(url.searchParams.keys())) {
if (key === 'embed' || key.toLowerCase().startsWith('va_')) {
if (EMBED_PARAMS.includes(key.toLowerCase())) {
url.searchParams.delete(key)
}
}