Skip to content

Commit

Permalink
test: add auth integration tests
Browse files Browse the repository at this point in the history
Add tests of the bundle web server with no auth and with a 'fixed' auth
configuration. Exercise cases where the user provides no credentials,
incorrect credentials, and correct credentials and the expected bundle
server responses for each.

Signed-off-by: Victoria Dye <[email protected]>
  • Loading branch information
vdye committed May 11, 2023
1 parent b6304c7 commit 0d12e27
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 3 deletions.
35 changes: 35 additions & 0 deletions test/integration/features/auth.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
Feature: Auth configuration on the web server

Background: The bundle server has an initialized route
Given no bundle server repository exists at route 'integration/auth'
Given a new remote repository with main branch 'main'
Given the remote is cloned
Given 5 commits are pushed to the remote branch 'main'
Given a bundle server repository is created at route 'integration/auth' for the remote

Scenario: With no auth config, bundle list can be accessed anonymously
Given the bundle web server was started at port 8080
When I request the bundle list
Then the response code is 200
Then the response is a valid bundle list

Scenario: If basic auth is required but none is sent, get a 401
Given an auth config with username 'my_username' and password 'p4sSW0rD!'
Given the bundle web server was started at port 8080 with auth config
When I request the bundle list
Then the response code is 401
Then the response is empty

Scenario: If basic auth is required and we send bad credentials, get a 404
Given an auth config with username 'my_username' and password 'p4sSW0rD!'
Given the bundle web server was started at port 8080 with auth config
When I request the bundle list with username 'my_userName' and password 'password!'
Then the response code is 404
Then the response is empty

Scenario: If basic auth is required and we send the right credentials, can access the bundle list
Given an auth config with username 'my_username' and password 'p4sSW0rD!'
Given the bundle web server was started at port 8080 with auth config
When I request the bundle list with username 'my_username' and password 'p4sSW0rD!'
Then the response code is 200
Then the response is a valid bundle list
24 changes: 24 additions & 0 deletions test/integration/features/step_definitions/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { IntegrationBundleServerWorld } from '../support/world'
import { Given } from '@cucumber/cucumber'
import * as fs from 'fs'
import * as path from 'path'
import * as crypto from 'crypto';

Given('an auth config with username {string} and password {string}',
async function (this: IntegrationBundleServerWorld, user: string, pass: string) {
const config = {
"mode": "fixed",
"parameters": {
"username": user,
"passwordHash": crypto.createHash('sha256').update(pass).digest('hex')
}
}
fs.writeFileSync(path.join(this.trashDirectory, "auth-config.json"), JSON.stringify(config))
}
)

Given('the bundle web server was started at port {int} with auth config',
async function (this: IntegrationBundleServerWorld, port: number) {
await this.bundleServer.startWebServer(port, path.join(this.trashDirectory, "auth-config.json"))
}
)
48 changes: 47 additions & 1 deletion test/integration/features/step_definitions/bundleServer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as assert from 'assert'
import { IntegrationBundleServerWorld } from '../support/world'
import { Given, Then } from '@cucumber/cucumber'
import { Given, When, Then } from '@cucumber/cucumber'
import * as utils from '../../../shared/support/utils'
import * as fs from 'fs'

Expand All @@ -18,6 +18,27 @@ Given('no bundle server repository exists at route {string}', async function (th
}
})

When('I request the bundle list', async function (this: IntegrationBundleServerWorld) {
this.requestResponse = await fetch(this.bundleServer.bundleUri(), {
method: 'GET',
headers: {
Accept: 'text/plain',
},
});
})

When('I request the bundle list with username {string} and password {string}',
async function (this: IntegrationBundleServerWorld, user: string, pass: string) {
this.requestResponse = await fetch(this.bundleServer.bundleUri(), {
method: 'GET',
headers: {
Accept: 'text/plain',
Authorization: 'Basic ' + Buffer.from(`${user}:${pass}`, 'utf8').toString('base64')
},
});
}
)

Then('a bundle server repository exists at route {string}', async function (this: IntegrationBundleServerWorld, route: string) {
var repoRoot = utils.repoRoot(route)
assert.equal(fs.existsSync(repoRoot), true)
Expand Down Expand Up @@ -71,3 +92,28 @@ Then('the route exists in the routes file', async function (this: IntegrationBun
throw new Error("Route not set")
}
})

Then('the response code is {int}', async function (this: IntegrationBundleServerWorld, code: number) {
if (!this.requestResponse) {
throw new Error("Request response not set")
}
assert.strictEqual(this.requestResponse.status, code)
})

Then('the response is a valid bundle list', async function (this: IntegrationBundleServerWorld) {
if (!this.requestResponse) {
throw new Error("Request response not set")
}

const data = await this.requestResponse.text()
assert.notStrictEqual(data, "")
})

Then('the response is empty', async function (this: IntegrationBundleServerWorld) {
if (!this.requestResponse) {
throw new Error("Request response not set")
}

const data = await this.requestResponse.text()
assert.strictEqual(data, "")
})
1 change: 1 addition & 0 deletions test/integration/features/support/world.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export class IntegrationBundleServerWorld extends BundleServerWorldBase {
local: ClonedRepository | undefined

commandResult: child_process.SpawnSyncReturns<Buffer> | undefined
requestResponse: Response | undefined

runCommand(commandArgs: string): void {
this.commandResult = child_process.spawnSync(`${this.parameters.bundleServerCommand} ${commandArgs}`, [], { shell: true })
Expand Down
8 changes: 6 additions & 2 deletions test/shared/classes/bundleServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,15 @@ export class BundleServer {
this.bundleWebServerCmd = bundleWebServerCmd
}

async startWebServer(port: number): Promise<void> {
async startWebServer(port: number, authConfig: string = ""): Promise<void> {
if (this.webServerProcess) {
throw new Error("Tried to start web server, but web server is already running")
}
const webServerProcess = child_process.spawn(this.bundleWebServerCmd, ["--port", String(port)])
let args = ["--port", String(port)]
if (authConfig !== "") {
args = args.concat(["--auth-config", authConfig])
}
const webServerProcess = child_process.spawn(this.bundleWebServerCmd, args)
this.webServerProcess = webServerProcess
this.bundleUriBase = `http://localhost:${port}/`

Expand Down

0 comments on commit 0d12e27

Please sign in to comment.