Skip to content

Commit

Permalink
Playwright tests for approve and reject change request (#452)
Browse files Browse the repository at this point in the history
* add playwright tests for systemuser change request

* refactor

* type fix

* Update build-deploy-at.yml

* fixes

* set correct env values in AT24

* remove unused import

* check for change request status after approve/reject

* Disable deploy and testing in AT24
  • Loading branch information
mgunnerud authored Dec 13, 2024
1 parent 5761e2a commit 236bc96
Show file tree
Hide file tree
Showing 6 changed files with 184 additions and 102 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/build-deploy-at.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ jobs:

strategy:
matrix:
environment: [AT22, AT23, AT24]
environment: [AT22]

steps:
- name: Checkout
Expand All @@ -80,7 +80,7 @@ jobs:
strategy:
fail-fast: false
matrix:
environment: [AT22, AT23, AT24]
environment: [AT22]
uses: "./.github/workflows/template-test-playwright.yml"
with:
environment: ${{ matrix.environment }}
Expand Down
159 changes: 107 additions & 52 deletions frontend/playwright/api-requests/ApiRequests.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Token } from './Token';

interface PostSystemUserRequestPayload {
systemId: string;
partyOrgNo: string;
Expand All @@ -11,16 +13,37 @@ interface PostSystemUserRequestPayload {
redirectUrl: string;
}

interface PostSystemUserChangeRequestPayload {
systemId: string;
partyOrgNo: string;
externalRef: string;
requiredRights: {
resource: {
id: string;
value: string;
}[];
}[];
redirectUrl: string;
}

export class ApiRequests {
public async cleanUpSystemUsers(systemUsers: { id: string }[], token: string): Promise<void> {
private tokenClass: Token;

constructor() {
this.tokenClass = new Token();
}

public async cleanUpSystemUsers(systemUsers: { id: string }[]): Promise<void> {
const token = await this.tokenClass.getPersonalAltinnToken();
for (const systemuser of systemUsers) {
await this.deleteSystemUser(token, systemuser.id);
}
}

public async getSystemUsers(token: string): Promise<string> {
public async getSystemUsers(): Promise<string> {
const endpoint = `v1/systemuser/${process.env.ALTINN_PARTY_ID}`;
const url = `${process.env.API_BASE_URL}${endpoint}`;
const token = await this.tokenClass.getPersonalAltinnToken();

try {
const response = await fetch(url, {
Expand Down Expand Up @@ -73,51 +96,95 @@ export class ApiRequests {
}
}

public async sendPostRequest<T>(
payload: PostSystemUserRequestPayload,
endpoint: string,
token: string,
): Promise<T> {
public async postSystemuserRequest(externalRef: string) {
const payload = this.generatePayloadSystemUserRequest(externalRef);
const endpoint = 'v1/systemuser/request/vendor';
const apiResponse = await this.sendPostRequest<{ confirmUrl: string; id: string }>(
payload,
endpoint,
);
return apiResponse; // Return the Confirmation URL to use in the test
}

public async approveSystemuserRequest(requestId: string) {
const endpoint = `v1/systemuser/request/${process.env.ALTINN_PARTY_ID}/${requestId}/approve`;
const url = `${process.env.API_BASE_URL}${endpoint}`;
const userToken = await this.tokenClass.getPersonalAltinnToken();

try {
const response = await fetch(url, {
method: 'POST',
headers: {
Authorization: `Bearer ${userToken}`,
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`, // Add the Authorization header
},
body: JSON.stringify(payload),
});

if (!response.ok) {
const errorBody = await response.text(); // Read the response body
console.error(`HTTP Error! Status: ${response.status}, Response Body: ${errorBody}`);
throw new Error(`HTTP error! Status: ${response.status}, Response Body: ${errorBody}`);
const errorBody = await response.text(); // Read the error body if needed
console.error('Failed to approve system user request:', response.status, errorBody);
throw new Error(`Failed to approve system user request: ${response.statusText}`);
}
const data = await response.json();
return data as Promise<T>; // Return the response data
} catch (error) {
console.error('Error:', error);
throw error; // Rethrow the error to handle it in the test
console.error('Error during system user request approval:', error);
throw new Error('System user user request approval. Check logs for details.');
}
}

/**
* Sends a GET request to fetch the last system request.
* @param endpoint The API endpoint (relative path).
* @param token The authorization token.
* @returns The response data as JSON.
*/
public async fetchLastSystemRequest<T>(endpoint: string, token: string): Promise<T> {
public async postSystemuserChangeRequest(externalRef: string) {
const payload = this.generatePayloadSystemUserChangeRequest(externalRef);
const endpoint = 'v1/systemuser/changerequest/vendor';
const apiResponse = await this.sendPostRequest<{ confirmUrl: string }>(payload, endpoint);
return apiResponse.confirmUrl; // Return the Confirmation URL to use in the test
}

public async getStatusForSystemUserRequest<T>(systemRequestId: string): Promise<T> {
const endpoint = `v1/systemuser/request/vendor/${systemRequestId}`;
return this.sendGetStatusRequest(endpoint);
}

public async getStatusForSystemUserChangeRequest<T>(systemRequestId: string): Promise<T> {
const endpoint = `v1/systemuser/changerequest/vendor/${systemRequestId}`;
return this.sendGetStatusRequest(endpoint);
}

private async sendGetStatusRequest(endpoint: string) {
const scopes =
'altinn:authentication/systemuser.request.read altinn:authentication/systemuser.request.write';
const token = await this.tokenClass.getEnterpriseAltinnToken(scopes);
const url = `${process.env.API_BASE_URL}${endpoint}`;

const response = await fetch(url, {
method: 'GET',
headers: {
Authorization: `Bearer ${token}`,
},
});

if (!response.ok) {
throw new Error(`Failed to fetch status for system user request. Status: ${response.status}`);
}

const data = await response.json();
return data;
}

private async sendPostRequest<T>(
payload: PostSystemUserRequestPayload | PostSystemUserChangeRequestPayload | null,
endpoint: string,
): Promise<T> {
const url = `${process.env.API_BASE_URL}${endpoint}`;
const scopes =
'altinn:authentication/systemuser.request.read altinn:authentication/systemuser.request.write';
const token = await this.tokenClass.getEnterpriseAltinnToken(scopes);
try {
const response = await fetch(url, {
method: 'GET',
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`, // Add the Authorization header
},
body: JSON.stringify(payload),
});

if (!response.ok) {
Expand All @@ -133,36 +200,11 @@ export class ApiRequests {
}
}

public async getStatusForSystemUserRequest<T>(
token: string,
systemRequestId: string,
): Promise<T> {
//Hardcode for now to test:
const endpoint = `v1/systemuser/request/vendor/${systemRequestId}`;
const url = `${process.env.API_BASE_URL}${endpoint}`;

const response = await fetch(url, {
method: 'GET',
headers: {
Authorization: `Bearer ${token}`,
},
});

if (!response.ok) {
throw new Error(`Failed to fetch status for system user request. Status: ${response.status}`);
}

const data = await response.json();
return data;
}

generatePayloadSystemUserRequest(): PostSystemUserRequestPayload {
const randomString = Date.now(); // Current timestamp in milliseconds
const randomNum = Math.random().toString(36);
private generatePayloadSystemUserRequest(externalRef: string): PostSystemUserRequestPayload {
return {
systemId: `${process.env.SYSTEM_ID}`,
partyOrgNo: `${process.env.ORG}`,
externalRef: `${randomNum}${randomString}`,
externalRef: externalRef,
rights: [
{
resource: [
Expand All @@ -172,6 +214,19 @@ export class ApiRequests {
},
],
},
],
redirectUrl: 'https://altinn.no',
};
}

private generatePayloadSystemUserChangeRequest(
externalRef: string,
): PostSystemUserChangeRequestPayload {
return {
systemId: `${process.env.SYSTEM_ID}`,
partyOrgNo: `${process.env.ORG}`,
externalRef: externalRef,
requiredRights: [
{
resource: [
{
Expand All @@ -184,4 +239,4 @@ export class ApiRequests {
redirectUrl: 'https://altinn.no',
};
}
}
}
4 changes: 2 additions & 2 deletions frontend/playwright/config/.env.at24
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ BASE_URL="https://at24.altinn.cloud"
SYSYEMUSER_URL="https://authn.ui.at24.altinn.cloud/authfront/ui/auth/creation"
API_BASE_URL="https://platform.at24.altinn.cloud/authentication/api/"

ALTINN_PARTY_ID="51359757"
ALTINN_USER_ID="20010849"
ALTINN_PARTY_ID="51321769"
ALTINN_USER_ID="20020071"
PID="14824497789"
ORG="310547891"
SYSTEM_ID="310547891_E2E - Playwright - Authentication"
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import test, { expect } from '@playwright/test';
import { ApiRequests } from '../api-requests/ApiRequests';
import { TestdataApi } from 'playwright/util/TestdataApi';

test.describe('Godkjenn og avvis Systembruker endringsforespørsel', () => {
let api: ApiRequests;

test.beforeEach(async () => {
api = new ApiRequests();
});

test('Avvis Systembruker endringsforespørsel', async ({ page }): Promise<void> => {
//Generate confirmUrl from API
const externalRef = TestdataApi.generateExternalRef();
const response = await api.postSystemuserRequest(externalRef);

await api.approveSystemuserRequest(response.id);

const confirmUrlChangeRequest = await api.postSystemuserChangeRequest(externalRef);

await page.goto(confirmUrlChangeRequest);
await page.getByRole('button', { name: 'Avvis' }).click();

//Expect user to be logged out
await expect(page).toHaveURL('https://info.altinn.no');

//Read from status api to verify that status is not Accepted after clicking "Avvis"
const statusApiRequest = await api.getStatusForSystemUserRequest<{ status: string }>(
response.id,
);
expect(statusApiRequest.status).toBe('Accepted');
});

test('Godkjenn Systembruker endringsforespørsel', async ({ page }): Promise<void> => {
const externalRef = TestdataApi.generateExternalRef();
const response = await api.postSystemuserRequest(externalRef);

await api.approveSystemuserRequest(response.id);

const confirmUrlChangeRequest = await api.postSystemuserChangeRequest(externalRef);

await page.goto(confirmUrlChangeRequest);
await page.getByRole('button', { name: 'Godkjenn' }).click();

//Expect user to be logged out
await expect(page).toHaveURL('https://info.altinn.no');
});
});
53 changes: 15 additions & 38 deletions frontend/playwright/e2eTests/approveSystemUserRequest.spec.ts
Original file line number Diff line number Diff line change
@@ -1,69 +1,46 @@
import test, { expect } from '@playwright/test';
import { ApiRequests } from '../api-requests/ApiRequests';
import { Token } from 'playwright/api-requests/Token';
import { LoginWithUserPage } from 'playwright/pages/loginPage';
import { TestdataApi } from 'playwright/util/TestdataApi';

test.describe('Godkjenn og avvis Systembrukerforespørsel', () => {
let token: Token;
let loginPage: LoginWithUserPage;
let api: ApiRequests;

test.beforeEach(async ({ page }) => {
test.beforeEach(async () => {
api = new ApiRequests();
token = new Token();
loginPage = new LoginWithUserPage(page);
});

test('Avvis Systembrukerforespørsel', async ({ page }): Promise<void> => {
//Generate confirmUrl from API
const systemUserRequestResponse = await prepareSystemUserRequest(api, token);
const externalRef = TestdataApi.generateExternalRef();
const response = await api.postSystemuserRequest(externalRef);

await page.goto(systemUserRequestResponse.confirmUrl);
await page.goto(response.confirmUrl);
await page.getByRole('button', { name: 'Avvis' }).click();

//Expect user to be logged out
await expect(loginPage.LOGIN_BUTTON).toBeVisible();
await expect(page).toHaveURL('https://info.altinn.no');

//Read from status api to verify that status is not rejected after clicking "Avvis"
const statusApiRequest = await getStatusForRequestApi(systemUserRequestResponse.id, token);
const statusApiRequest = await api.getStatusForSystemUserRequest<{ status: string }>(
response.id,
);
expect(statusApiRequest.status).toBe('Rejected');
});

test('Godkjenn Systembrukerforespørsel', async ({ page }): Promise<void> => {
const systemUserRequestResponse = await prepareSystemUserRequest(api, token);
const externalRef = TestdataApi.generateExternalRef();
const response = await api.postSystemuserRequest(externalRef);

await page.goto(systemUserRequestResponse.confirmUrl);
await page.goto(response.confirmUrl);
await page.getByRole('button', { name: 'Godkjenn' }).click();

//Expect user to be logged out
await expect(loginPage.LOGIN_BUTTON).toBeVisible();
await expect(page).toHaveURL('https://info.altinn.no');

//Read from status api to verify that status is not Accepted after clicking "Avvis"
const statusApiRequest = await getStatusForRequestApi(systemUserRequestResponse.id, token);
const statusApiRequest = await api.getStatusForSystemUserRequest<{ status: string }>(
response.id,
);
expect(statusApiRequest.status).toBe('Accepted');
});

async function prepareSystemUserRequest(api: ApiRequests, tokenclass: Token) {
const payload = api.generatePayloadSystemUserRequest();
const scopes =
'altinn:authentication/systemuser.request.read altinn:authentication/systemuser.request.write';
const token = await tokenclass.getEnterpriseAltinnToken(scopes);
const endpoint = 'v1/systemuser/request/vendor';
const apiResponse = await api.sendPostRequest<{ confirmUrl: string; id: string }>(
payload,
endpoint,
token,
);
return { confirmUrl: apiResponse.confirmUrl, id: apiResponse.id }; // Return the Confirmation URL and the ID to use in the test
}

async function getStatusForRequestApi(id: string, tokenclass: Token) {
const scopes =
'altinn:authentication/systemuser.request.read altinn:authentication/systemuser.request.write';
const token = await tokenclass.getEnterpriseAltinnToken(scopes);
const statusResponse = api.getStatusForSystemUserRequest<{ status: string }>(token, id);
return statusResponse;
}
});
});
Loading

0 comments on commit 236bc96

Please sign in to comment.