Skip to content

Commit

Permalink
fix: Deployment-api e2e-tests (#440)
Browse files Browse the repository at this point in the history
* fix deployment-api e2e-tests

* fix: Changes from lint

* remove cleanup from gh action

---------

Co-authored-by: cloud-sdk-js <[email protected]>
  • Loading branch information
shibeshduw and cloud-sdk-js authored Jan 10, 2025
1 parent cee5d05 commit d086e4b
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 119 deletions.
2 changes: 0 additions & 2 deletions .github/workflows/e2e-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,6 @@ jobs:
fi
done
wget -qO- -S --content-on-error localhost:8080
- name: 'Cleanup Deployments'
run: pnpm e2e-tests cleanup-deployments
- name: 'Execute E2E Tests'
run: pnpm test:e2e
- name: 'Slack Notification'
Expand Down
2 changes: 1 addition & 1 deletion tests/e2e-tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ End-to-end tests for the SAP Cloud SDK for AI.

## Remote Testing

Trigger the [GitHub Action](https://github.com/SAP/ai-sdk-js/actions/workflows/e2e-test.yml).
Trigger the [GitHub Action](https://github.com/SAP/ai-sdk-js/actions/workflows/e2e-tests.yaml).
146 changes: 30 additions & 116 deletions tests/e2e-tests/src/deployment-api.test.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,23 @@
import { DeploymentApi } from '@sap-ai-sdk/ai-api';
import { getDeployments, createDeployment } from '@sap-ai-sdk/sample-code';
import { loadEnv } from './utils/load-env.js';
import {
configurationId,
resourceGroup,
waitForDeploymentToReachStatus
} from './utils/ai-api-utils.js';
import type { AiApiError, AiDeploymentList } from '@sap-ai-sdk/ai-api';
import { configurationId, resourceGroup } from './utils/ai-api-utils.js';

loadEnv();

describe('DeploymentApi', () => {
let createdDeploymentId: string | undefined;
let initialDeployments: AiDeploymentList | undefined;

beforeAll(async () => {
it('should get all deployments', async () => {
const queryResponse = await getDeployments(resourceGroup);
expect(queryResponse).toBeDefined();
initialDeployments = queryResponse;
expect(queryResponse).toMatchObject({
count: expect.any(Number),
resources: expect.any(Array)
});
});

it('should create a deployment and wait for it to run', async () => {
it('should create and delete a deployment', async () => {
const createResponse = await createDeployment(
configurationId,
resourceGroup
Expand All @@ -32,123 +29,40 @@ describe('DeploymentApi', () => {
})
);

const runningDeployment = await waitForDeploymentToReachStatus(
createResponse.id,
'RUNNING'
);
expect(runningDeployment).toEqual(
expect.objectContaining({
status: 'RUNNING',
deploymentUrl: expect.any(String)
})
);
createdDeploymentId = createResponse.id;

createdDeploymentId = runningDeployment.id;
}, 200000);
// A deployment initially has status: 'UNKNOWN' and can be deleted immediately
// without needing to stop the deployment

it('should stop the deployment', async () => {
const deploymentId = await checkCreatedDeployment(
const deleteResponse = await DeploymentApi.deploymentDelete(
createdDeploymentId,
'RUNNING'
);

const modifyResponse = await DeploymentApi.deploymentModify(
deploymentId,
{ targetStatus: 'STOPPED' },
{ 'AI-Resource-Group': resourceGroup }
{
'AI-Resource-Group': resourceGroup
}
).execute();
expect(modifyResponse).toEqual(
expect.objectContaining({
message: 'Deployment modification scheduled'
})
);

const stoppedDeployment = await waitForDeploymentToReachStatus(
deploymentId,
'STOPPED'
);
expect(stoppedDeployment).toEqual(
expect.objectContaining({
status: 'STOPPED'
})
);
}, 200000);

it('should delete the deployment', async () => {
const deploymentId = await checkCreatedDeployment(
createdDeploymentId,
'STOPPED'
);

const deleteResponse = await DeploymentApi.deploymentDelete(deploymentId, {
'AI-Resource-Group': resourceGroup
}).execute();
expect(deleteResponse).toEqual(
expect.objectContaining({
message: 'Deletion scheduled'
})
);

// Wait for deletion to complete
await new Promise(r => setTimeout(r, 30000));
await expect(
DeploymentApi.deploymentGet(
deploymentId,
{},
{ 'AI-Resource-Group': resourceGroup }
).execute()
).rejects.toThrow();
}, 150000);

it('should validate consistency of deployments after test flow', async () => {
const queryResponse = await getDeployments(resourceGroup);
expect(queryResponse).toBeDefined();

const initialFilteredDeployments = filterDeployments(
initialDeployments,
createdDeploymentId
);
const finalFilteredDeployments = filterDeployments(
queryResponse,
createdDeploymentId
);
expect(finalFilteredDeployments.resources).toStrictEqual(
initialFilteredDeployments.resources
);
const deletedDeployment = await DeploymentApi.deploymentGet(
createdDeploymentId,
{},
{ 'AI-Resource-Group': resourceGroup }
).execute();
expect(deletedDeployment.targetStatus).toBe('DELETED');
});
});

const filterDeployments = (
deployments: AiDeploymentList | undefined,
createdDeployentId: string | undefined
) => ({
...deployments,
resources: deployments?.resources
.filter(deployment => deployment.id === createdDeployentId)
// eslint-disable-next-line @typescript-eslint/no-unused-vars
.map(({ modifiedAt, ...rest }) => rest)
});
afterAll(async () => {
// Wait for deployment to be deleted
await new Promise(r => setTimeout(r, 60000));
const finalDeployments = await getDeployments(resourceGroup);

async function checkCreatedDeployment(
deploymentId: string | undefined,
status: 'RUNNING' | 'STOPPED'
): Promise<string> {
if (!deploymentId) {
try {
const response = await getDeployments(resourceGroup, status);
if (!response.count) {
throw new Error(
`No ${status} deployments found, please ${status === 'RUNNING' ? 'create' : 'stop'} a deployment first to ${status === 'RUNNING' ? 'modify' : 'delete'} it.`
);
}
return response.resources[0].id;
} catch (error: any) {
if (error.response) {
const apiError = error.response.data.error as AiApiError;
throw new Error(`Request failed: ${apiError.message}`);
}
throw error;
if (finalDeployments.count) {
expect(
finalDeployments.resources.map(deployment => deployment.id)
).not.toContain(createdDeploymentId);
}
}
return deploymentId;
}
}, 75000);
});

0 comments on commit d086e4b

Please sign in to comment.