Files
bruno/tests/auth/oauth1/oauth1-runner.spec.ts

223 lines
8.6 KiB
TypeScript

import fs from 'fs';
import path from 'path';
import { test, expect } from '../../../playwright';
import {
sendRequestAndWaitForResponse, closeAllCollections, selectEnvironment,
openCollection, openRequest, selectResponsePaneTab
} from '../../utils/page';
import { runCollection, validateRunnerResults } from '../../utils/page/runner';
// The test PEM file is gitignored (*.pem). Write it to both fixture directories
// at module load time so collectionFixturePath includes it when copying.
const { TEST_RSA_PRIVATE_KEY } = require('../../../packages/bruno-tests/src/auth/oauth1');
const fixtureBase = path.join(__dirname, 'fixtures', 'collections');
for (const subdir of ['bru', 'yml']) {
const pemPath = path.join(fixtureBase, subdir, 'test-private-key.pem');
if (!fs.existsSync(pemPath)) {
fs.writeFileSync(pemPath, TEST_RSA_PRIVATE_KEY);
}
}
const BRU_COLLECTION = 'oauth1-testbench-bru';
const YML_COLLECTION = 'oauth1-testbench-yml';
const requests = [
{ name: 'OAuth1 HMAC-SHA1 200', status: 200 },
{ name: 'OAuth1 HMAC-SHA1 401', status: 401 },
{ name: 'OAuth1 HMAC-SHA1 POST 200', status: 200 },
{ name: 'OAuth1 HMAC-SHA1 Query Params 200', status: 200 },
{ name: 'OAuth1 HMAC-SHA256 200', status: 200 },
{ name: 'OAuth1 HMAC-SHA256 401', status: 401 },
{ name: 'OAuth1 HMAC-SHA512 200', status: 200 },
{ name: 'OAuth1 HMAC-SHA512 401', status: 401 },
{ name: 'OAuth1 PLAINTEXT 200', status: 200 },
{ name: 'OAuth1 PLAINTEXT 401', status: 401 },
{ name: 'OAuth1 PLAINTEXT Query Params 200', status: 200 },
{ name: 'OAuth1 RSA-SHA1 200', status: 200 },
{ name: 'OAuth1 RSA-SHA1 Query Params 200', status: 200 },
{ name: 'OAuth1 RSA-SHA256 200', status: 200 },
{ name: 'OAuth1 RSA-SHA512 200', status: 200 },
{ name: 'OAuth1 RSA-SHA1 Variable Key 200', status: 200 },
{ name: 'OAuth1 RSA-SHA1 File Key 200', status: 200 },
{ name: 'OAuth1 HMAC-SHA1 Body 200', status: 200 },
{ name: 'OAuth1 PLAINTEXT Body 200', status: 200 },
{ name: 'OAuth1 HMAC-SHA256 Body 200', status: 200 },
{ name: 'OAuth1 RSA-SHA1 Body 200', status: 200 },
{ name: 'OAuth1 RSA-SHA1 Body formurlencoded 200', status: 200 },
{ name: 'OAuth1 HMAC-SHA1 Body JSON 200', status: 200 }
];
const sendAllRequests = async (page, collectionName: string) => {
await openCollection(page, collectionName);
await selectEnvironment(page, 'Local', 'collection');
for (const { name, status } of requests) {
await test.step(name, async () => {
await openRequest(page, collectionName, name);
await sendRequestAndWaitForResponse(page, status);
});
}
};
const runAndValidate = async (page, collectionName: string) => {
await runCollection(page, collectionName);
await validateRunnerResults(page, {
totalRequests: requests.length,
passed: requests.length,
failed: 0
});
};
/**
* After sending a request, switch to the Timeline tab, expand the latest timeline row,
* and return its locator. The expanded detail panel defaults to the Request tab,
* which shows the sent URL, headers and body (what OAuth1 placement assertions need).
*/
const openTimelineRequest = async (page) => {
await selectResponsePaneTab(page, 'Timeline');
const row = page.locator('.timeline-container .tl-row-wrap').first();
await row.locator('.tl-row').click();
return row;
};
const verifyPlacement = async (page, collectionName: string, requestName: string, placement: 'header' | 'query' | 'body') => {
await openRequest(page, collectionName, requestName);
await sendRequestAndWaitForResponse(page, 200);
const row = await openTimelineRequest(page);
const detail = row.locator('.tl-detail');
if (placement === 'header') {
const headers = detail.locator('.tl-headers-table');
await expect(headers).toContainText('Authorization');
await expect(headers).toContainText('OAuth');
} else if (placement === 'query') {
await expect(detail.locator('.tl-header-url-text')).toContainText('oauth_consumer_key');
} else {
// Body: oauth params should be in the request body, not in URL or Authorization header
await expect(detail.locator('.tl-header-url-text')).not.toContainText('oauth_consumer_key');
const body = detail.locator('.tl-block').filter({
has: page.locator('.tl-block-h', { hasText: 'Body' })
});
await expect(body).toContainText('oauth_consumer_key');
}
};
test.describe('OAuth 1.0 Runner', () => {
test.afterAll(async ({ pageWithUserData: page }) => {
await closeAllCollections(page);
});
test.describe('[bru]', () => {
test('Send individual requests', async ({ pageWithUserData: page }) => {
test.setTimeout(3 * 60 * 1000);
await sendAllRequests(page, BRU_COLLECTION);
});
test('Run collection and verify all assertions pass', async ({ pageWithUserData: page }) => {
test.setTimeout(3 * 60 * 1000);
await runAndValidate(page, BRU_COLLECTION);
});
test('Verify Add Params To placement via timeline', async ({ pageWithUserData: page }) => {
test.setTimeout(3 * 60 * 1000);
await openCollection(page, BRU_COLLECTION);
await selectEnvironment(page, 'Local', 'collection');
await test.step('Header: HMAC-SHA1', async () => {
await verifyPlacement(page, BRU_COLLECTION, 'OAuth1 HMAC-SHA1 200', 'header');
});
await test.step('Query Params: HMAC-SHA1', async () => {
await verifyPlacement(page, BRU_COLLECTION, 'OAuth1 HMAC-SHA1 Query Params 200', 'query');
});
await test.step('Query Params: PLAINTEXT', async () => {
await verifyPlacement(page, BRU_COLLECTION, 'OAuth1 PLAINTEXT Query Params 200', 'query');
});
await test.step('Query Params: RSA-SHA1', async () => {
await verifyPlacement(page, BRU_COLLECTION, 'OAuth1 RSA-SHA1 Query Params 200', 'query');
});
await test.step('Body: HMAC-SHA1', async () => {
await verifyPlacement(page, BRU_COLLECTION, 'OAuth1 HMAC-SHA1 Body 200', 'body');
});
await test.step('Body: PLAINTEXT', async () => {
await verifyPlacement(page, BRU_COLLECTION, 'OAuth1 PLAINTEXT Body 200', 'body');
});
await test.step('Body: HMAC-SHA256', async () => {
await verifyPlacement(page, BRU_COLLECTION, 'OAuth1 HMAC-SHA256 Body 200', 'body');
});
await test.step('Body: RSA-SHA1', async () => {
await verifyPlacement(page, BRU_COLLECTION, 'OAuth1 RSA-SHA1 Body 200', 'body');
});
await test.step('Body: HMAC-SHA1 JSON (non-form body)', async () => {
await verifyPlacement(page, BRU_COLLECTION, 'OAuth1 HMAC-SHA1 Body JSON 200', 'body');
});
});
});
test.describe('[yml]', () => {
test('Send individual requests', async ({ pageWithUserData: page }) => {
test.setTimeout(3 * 60 * 1000);
await sendAllRequests(page, YML_COLLECTION);
});
test('Run collection and verify all assertions pass', async ({ pageWithUserData: page }) => {
test.setTimeout(3 * 60 * 1000);
await runAndValidate(page, YML_COLLECTION);
});
test('Verify Add Params To placement via timeline', async ({ pageWithUserData: page }) => {
test.setTimeout(3 * 60 * 1000);
await openCollection(page, YML_COLLECTION);
await selectEnvironment(page, 'Local', 'collection');
await test.step('Header: HMAC-SHA1', async () => {
await verifyPlacement(page, YML_COLLECTION, 'OAuth1 HMAC-SHA1 200', 'header');
});
await test.step('Query Params: HMAC-SHA1', async () => {
await verifyPlacement(page, YML_COLLECTION, 'OAuth1 HMAC-SHA1 Query Params 200', 'query');
});
await test.step('Query Params: PLAINTEXT', async () => {
await verifyPlacement(page, YML_COLLECTION, 'OAuth1 PLAINTEXT Query Params 200', 'query');
});
await test.step('Query Params: RSA-SHA1', async () => {
await verifyPlacement(page, YML_COLLECTION, 'OAuth1 RSA-SHA1 Query Params 200', 'query');
});
await test.step('Body: HMAC-SHA1', async () => {
await verifyPlacement(page, YML_COLLECTION, 'OAuth1 HMAC-SHA1 Body 200', 'body');
});
await test.step('Body: PLAINTEXT', async () => {
await verifyPlacement(page, YML_COLLECTION, 'OAuth1 PLAINTEXT Body 200', 'body');
});
await test.step('Body: HMAC-SHA256', async () => {
await verifyPlacement(page, YML_COLLECTION, 'OAuth1 HMAC-SHA256 Body 200', 'body');
});
await test.step('Body: RSA-SHA1', async () => {
await verifyPlacement(page, YML_COLLECTION, 'OAuth1 RSA-SHA1 Body 200', 'body');
});
await test.step('Body: HMAC-SHA1 JSON (non-form body)', async () => {
await verifyPlacement(page, YML_COLLECTION, 'OAuth1 HMAC-SHA1 Body JSON 200', 'body');
});
});
});
});