Skip to content
Open
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
5e03d55
draft catalog service
ikethecoder Dec 22, 2025
e5e8729
upd data model for sdx entities
ikethecoder Dec 24, 2025
90704ad
upds to sdx api
ikethecoder Dec 26, 2025
2cd469e
fix spec loader
ikethecoder Dec 26, 2025
0632486
fix spectral errors
ikethecoder Dec 26, 2025
ad53d0f
add spectral rules
ikethecoder Dec 26, 2025
b9e0672
spectral adjustments
ikethecoder Dec 26, 2025
8be2afe
upd openapi tags to be alphabetical
ikethecoder Dec 26, 2025
f07eece
refactor subsystem
ikethecoder Dec 30, 2025
875c036
comment out future work
ikethecoder Dec 30, 2025
45e893d
upd system owner role
ikethecoder Dec 30, 2025
e8d9d00
make the apispec public
ikethecoder Dec 30, 2025
b4b0066
include all scopes in sdx v1
ikethecoder Dec 30, 2025
7fc27a2
add cypress tests for new sdx apis
ikethecoder Jan 7, 2026
2f8bc30
adj sdx v1 apis
ikethecoder Jan 8, 2026
b825e2c
remove all related to runtime groups
ikethecoder Jan 8, 2026
d57fc71
cleanup some runtime group refs
ikethecoder Jan 8, 2026
daa4ced
fix local db
ikethecoder Jan 8, 2026
9e8dc0b
fix unit test
ikethecoder Jan 8, 2026
647b75c
upd ks integrated test init
ikethecoder Jan 8, 2026
6eb1190
upd test data for passing sonar
ikethecoder Jan 8, 2026
c6e0d0b
sonar fix
ikethecoder Jan 8, 2026
c60fb18
sonar trying to resolve
ikethecoder Jan 8, 2026
d8f5219
fixes for cypress tests
ikethecoder Jan 9, 2026
59845be
sonar node fix
ikethecoder Jan 9, 2026
fc65b12
fix cypress tests
ikethecoder Jan 9, 2026
c47fce4
upd authz decision matrix
ikethecoder Jan 9, 2026
b78f202
Merge branch 'dev' into feature/sdx-service
ikethecoder Mar 13, 2026
f054068
APS-3966, APS-4050 - Runtime Groups (#1331)
ikethecoder Mar 13, 2026
a82e09c
cleanup a botched merge
ikethecoder Mar 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,7 @@ e2e/cypress/fixtures/state/*.pub
e2e/cypress/fixtures/state/*.pem
e2e/cypress/fixtures/state/scanResult.json
e2e/cypress/fixtures/state/scanID.json
e2e/cypress/downloads/
e2e/cypress/downloads/

openapi.yaml
routes.ts
2 changes: 2 additions & 0 deletions .spectral.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
extends:
- https://raw.githubusercontent.com/bcgov/csit-api-governance-spectral-style-guide/refs/heads/main/spectral/basic-ruleset.yaml
1 change: 1 addition & 0 deletions e2e/cypress.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export default defineConfig({
'./cypress/tests/18-*/*.ts',
'./cypress/tests/19-*/*.ts',
'./cypress/tests/20-*/*.ts',
'./cypress/tests/21-*/**/*.ts',
]
return config
},
Expand Down
200 changes: 121 additions & 79 deletions e2e/cypress/support/auth-commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ let headers: any
const login = new LoginPage()

let requestBody: any = {}
let queryString: any = undefined
interface formDataRequestOptions {
method: string
url: string
Expand Down Expand Up @@ -86,8 +87,9 @@ Cypress.Commands.add('createGateway', (gatewayid?: string, displayname?: string)
}
cy.setHeaders({ 'Content-Type': 'application/json' })
cy.setRequestBody(payload)
return cy.callAPI('ds/api/v3/gateways', 'POST').then(
({ apiRes: { body, status } }: any) => {
return cy
.callAPI('ds/api/v3/gateways', 'POST')
.then(({ apiRes: { body, status } }: any) => {
cy.log(JSON.stringify(body, null, 2))
expect(status).to.be.equal(200)
if (payload.gatewayId) {
Expand All @@ -97,8 +99,7 @@ Cypress.Commands.add('createGateway', (gatewayid?: string, displayname?: string)
expect(body.displayName).to.be.equal(payload.displayName)
}
return cy.wrap(body)
}
)
})
})

Cypress.Commands.add('deleteGatewayCli', (gatewayid: string, force: boolean = false) => {
Expand All @@ -107,20 +108,23 @@ Cypress.Commands.add('deleteGatewayCli', (gatewayid: string, force: boolean = fa
(response) => {
console.log(response)
expect(response.stdout).to.contain('Gateway destroyed: ' + gatewayid)
})
}
)
})
})

Cypress.Commands.add('activateGateway', (gatewayId: string, checkNoNamespace: boolean = false) => {
const getAllNsQuery = `
Cypress.Commands.add(
'activateGateway',
(gatewayId: string, checkNoNamespace: boolean = false) => {
const getAllNsQuery = `
query GetNamespaces {
allNamespaces {
id
name
}
}
`
const currentNsQuery = `
const currentNsQuery = `
query GetCurrentNamespace {
currentNamespace {
name
Expand All @@ -129,33 +133,39 @@ query GetNamespaces {
}
}
`
cy.log('< Activating namespace - ' + gatewayId)
// get the (true) id for the namespace
cy.setHeaders({ 'Content-Type': 'application/json' })
return cy.gqlQuery(getAllNsQuery).then((response) => {
const nsdata = response.apiRes.body.data.allNamespaces.find((ns: { name: string }) => ns.name === gatewayId)
if (nsdata) {
return nsdata.id
} else {
if (checkNoNamespace) {
return 'Namespace not found'
} else {
throw new Error('Namespace not found')
}
}
}).then((namespaceId) => {
if (namespaceId === 'Namespace not found') {
return namespaceId;
}
// then activate the namespace
cy.log('< Activating namespace - ' + gatewayId)
// get the (true) id for the namespace
cy.setHeaders({ 'Content-Type': 'application/json' })
cy.callAPI(`admin/switch/${namespaceId}`, 'PUT')
return cy.gqlQuery(currentNsQuery).then((response) => {
const currentNs = response.apiRes.body.data.currentNamespace
expect(currentNs.name).to.eq(gatewayId)
})
})
})
return cy
.gqlQuery(getAllNsQuery)
.then((response) => {
const nsdata = response.apiRes.body.data.allNamespaces.find(
(ns: { name: string }) => ns.name === gatewayId
)
if (nsdata) {
return nsdata.id
} else {
if (checkNoNamespace) {
return 'Namespace not found'
} else {
throw new Error('Namespace not found')
}
}
})
.then((namespaceId) => {
if (namespaceId === 'Namespace not found') {
return namespaceId
}
// then activate the namespace
cy.setHeaders({ 'Content-Type': 'application/json' })
cy.callAPI(`admin/switch/${namespaceId}`, 'PUT')
return cy.gqlQuery(currentNsQuery).then((response) => {
const currentNs = response.apiRes.body.data.currentNamespace
expect(currentNs.name).to.eq(gatewayId)
})
})
}
)

Cypress.Commands.add('getGateways', () => {
const getAllNsQuery = `
Expand Down Expand Up @@ -549,42 +559,72 @@ Cypress.Commands.add('setHeaders', (headerValues: any) => {
headers = headerValues
})

Cypress.Commands.add('setHeader', (key: string, value: string) => {
headers[key] = value
})

Cypress.Commands.add('setRequestBody', (body: any) => {
requestBody = JSON.stringify(body)
})

Cypress.Commands.add('setRequestFormData', (body: FormData) => {
requestBody = body
})

Cypress.Commands.add('setQueryString', (qs: any) => {
queryString = qs
})

Cypress.Commands.add('setAuthorizationToken', (token: string) => {
headers['Authorization'] = 'Bearer ' + token
})

Cypress.Commands.add('callAPI', (endPoint: string, methodType: string) => {
let body = '{}'
let requestData: any = {}
if (methodType.toUpperCase() === 'PUT' || methodType.toUpperCase() === 'POST') {
body = requestBody
}

requestData['appname'] = 'Test1'
requestData['url'] = Cypress.env('BASE_URL') + '/' + endPoint
requestData['headers'] = headers
requestData['body'] = ''
requestData['method'] = methodType
Cypress.Commands.add(
'callAPI',
(endPoint: string, methodType: string, formData?: boolean) => {
let body = '{}'
let requestData: any = {}
if (methodType.toUpperCase() === 'PUT' || methodType.toUpperCase() === 'POST') {
body = requestBody
}

cy.request({
url: Cypress.env('BASE_URL') + '/' + endPoint,
method: methodType,
body,
headers,
failOnStatusCode: false,
}).then((apiResponse) => {
// You can also return data or use it in further tests
const responseData = {
apiRes: apiResponse,
requestData['appname'] = 'Test1'
requestData['url'] = Cypress.env('BASE_URL') + '/' + endPoint
requestData['headers'] = headers
requestData['body'] = ''
requestData['method'] = methodType

const newHeaders = {
...headers,
...(formData
? { Accept: 'application/json', 'Content-Type': 'multipart/form-data' }
: {}),
}
// cy.addToAstraScanIdList(response2.body.status)
return responseData
})
})

cy.request({
url: Cypress.env('BASE_URL') + '/' + endPoint,
method: methodType,
body: body,
qs: queryString,
headers: newHeaders,
failOnStatusCode: false,
})
.then((res) => {
if (formData || res.body instanceof ArrayBuffer) {
res.body = JSON.parse(new TextDecoder().decode(res.body))
}
return res
})
.then((apiResponse) => {
// You can also return data or use it in further tests
const responseData = {
apiRes: apiResponse,
}
// cy.addToAstraScanIdList(response2.body.status)
return responseData
})
}
)

Cypress.Commands.add('makeAPIRequest', (endPoint: string, methodType: string) => {
let body = {}
Expand Down Expand Up @@ -644,25 +684,27 @@ Cypress.Commands.add('makeAPIRequest', (endPoint: string, methodType: string) =>

Cypress.Commands.add('gqlQuery', (query, variables = {}) => {
cy.loginByAuthAPI('', '').then((token_res: any) => {
cy.setHeaders({
'Accept': 'application/json',
'Content-Type': 'application/json'
cy.setHeaders({
Accept: 'application/json',
'Content-Type': 'application/json',
})
cy.setAuthorizationToken(token_res.token)
return cy.request({
url: Cypress.env('BASE_URL') + '/gql/api',
method: 'POST',
headers,
body: JSON.stringify({ query, variables }),
failOnStatusCode: false,
}).then((apiResponse) => {
// You can also return data or use it in further tests
const responseData = {
apiRes: apiResponse,
}
// cy.addToAstraScanIdList(response2.body.status)
return responseData
})
return cy
.request({
url: Cypress.env('BASE_URL') + '/gql/api',
method: 'POST',
headers,
body: JSON.stringify({ query, variables }),
failOnStatusCode: false,
})
.then((apiResponse) => {
// You can also return data or use it in further tests
const responseData = {
apiRes: apiResponse,
}
// cy.addToAstraScanIdList(response2.body.status)
return responseData
})
})
})

Expand All @@ -678,9 +720,9 @@ Cypress.Commands.add('getUserSession', () => {
cy.request({
method: 'GET',
url: Cypress.config('baseUrl') + '/admin/session',
failOnStatusCode: true
failOnStatusCode: true,
}).as('login')
});
})

Cypress.Commands.add('interceptUserSession', () => {
cy.intercept(Cypress.config('baseUrl') + '/admin/session').as('login')
Expand Down
27 changes: 17 additions & 10 deletions e2e/cypress/support/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

declare namespace Cypress {
interface Namespace {
id: string;
name: string;
id: string
name: string
}

interface Chainable<Subject> {
Expand Down Expand Up @@ -33,10 +33,7 @@ declare namespace Cypress {

preserveCookiesDefaults(): void

createGateway(
gatewayid?: string,
displayname?: string,
): Chainable<any>
createGateway(gatewayid?: string, displayname?: string): Chainable<any>

deleteGatewayCli(gatewayid: string, force: boolean): Chainable<any>

Expand Down Expand Up @@ -93,18 +90,28 @@ declare namespace Cypress {

setHeaders(headerValues: any): void

setHeader(key: string, value: string): void

setRequestBody(requestBody: any): void

setQueryString(qs: any): void

setRequestFormData(body: FormData): void

setAuthorizationToken(token: string): void

gqlQuery<T = any>(query: string, variables?: Record<string, any>): Chainable<T>

callAPI(endPoint: string, methodType: string): Chainable<Cypress.Response<any>>

callAPI(
endPoint: string,
methodType: string,
formData?: boolean
): Chainable<Cypress.Response<any>>

makeAPIRequest(endPoint: string, methodType: string): Chainable<Cypress.Response<any>>

getUserSession(): Chainable<Cypress.Response<any>>

interceptUserSession(): Chainable<Cypress.Response<any>>

compareJSONObjects(
Expand Down
4 changes: 2 additions & 2 deletions e2e/cypress/support/prep-commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Cypress.Commands.add('buildOrgGatewayDatasetAndProduct', (): Cypress.Chainable<a
member: {
email: 'janis@testmail.com',
},
roles: ['organization-admin'],
roles: ['organization-admin', 'system-owner'],
},
],
}
Expand Down Expand Up @@ -143,7 +143,7 @@ Cypress.Commands.add('buildOrgGatewayDatasetAndProduct', (): Cypress.Chainable<a
expect(JSON.stringify(body)).to.be.equal(JSON.stringify(match))

// New Gateway
cy.setRequestBody({})
cy.setRequestBody({ displayName: `Gateway ${payload.name}` })
return cy
.callAPI('ds/api/v3/gateways', 'POST')
.then(({ apiRes: { body, status } }: any) => {
Expand Down
Loading
Loading