chore: kanban template
This commit is contained in:
106
e2e/tests/steps/content.steps.ts
Normal file
106
e2e/tests/steps/content.steps.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
import { Given, When, Then } from '@cucumber/cucumber'
|
||||
import { expect } from '@playwright/test'
|
||||
import type { AppWorld } from '../support/world.js'
|
||||
import { config } from '../support/types.js'
|
||||
|
||||
interface ContentWorld extends AppWorld {
|
||||
cardId: string
|
||||
uploadUrl: string
|
||||
signedUrl: string
|
||||
uploadStatus: number
|
||||
}
|
||||
|
||||
Given('a card exists', async function (this: ContentWorld) {
|
||||
const res = await fetch(`${config.apiUrl}/cards`, {
|
||||
method: 'POST',
|
||||
headers: { 'content-type': 'application/json' },
|
||||
body: JSON.stringify({ title: 'Attachment test card' }),
|
||||
})
|
||||
expect(res.ok, `POST /cards failed: ${res.status}`).toBe(true)
|
||||
const body = (await res.json()) as { cardId: string }
|
||||
this.cardId = body.cardId
|
||||
})
|
||||
|
||||
When(
|
||||
'I request an upload URL for filename {string} and content type {string}',
|
||||
async function (this: ContentWorld, fileName: string, contentType: string) {
|
||||
const res = await fetch(
|
||||
`${config.apiUrl}/cards/${this.cardId}/attachments/upload-url`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: { 'content-type': 'application/json' },
|
||||
body: JSON.stringify({ cardId: this.cardId, fileName, contentType }),
|
||||
},
|
||||
)
|
||||
expect(res.ok, `upload-url request failed: ${res.status} ${await res.text()}`).toBe(true)
|
||||
const body = (await res.json()) as { uploadUrl: string }
|
||||
this.uploadUrl = body.uploadUrl
|
||||
},
|
||||
)
|
||||
|
||||
When(
|
||||
'I PUT {string} to the upload URL',
|
||||
async function (this: ContentWorld, content: string) {
|
||||
const res = await fetch(this.uploadUrl, {
|
||||
method: 'PUT',
|
||||
body: content,
|
||||
headers: { 'content-type': 'text/plain' },
|
||||
})
|
||||
this.uploadStatus = res.status
|
||||
},
|
||||
)
|
||||
|
||||
Then(
|
||||
'the upload response status is 200 or 201',
|
||||
function (this: ContentWorld) {
|
||||
expect(
|
||||
this.uploadStatus === 200 || this.uploadStatus === 201,
|
||||
`expected 200 or 201 from upload PUT, got ${this.uploadStatus}`,
|
||||
).toBe(true)
|
||||
},
|
||||
)
|
||||
|
||||
When(
|
||||
'I request a signed download URL for filename {string}',
|
||||
async function (this: ContentWorld, fileName: string) {
|
||||
const res = await fetch(
|
||||
`${config.apiUrl}/cards/${this.cardId}/attachments/${encodeURIComponent(fileName)}/signed-url`,
|
||||
)
|
||||
expect(res.ok, `signed-url request failed: ${res.status} ${await res.text()}`).toBe(true)
|
||||
const body = (await res.json()) as { signedUrl: string }
|
||||
this.signedUrl = body.signedUrl
|
||||
},
|
||||
)
|
||||
|
||||
Then(
|
||||
'the signed URL response contains a signedUrl',
|
||||
function (this: ContentWorld) {
|
||||
expect(typeof this.signedUrl).toBe('string')
|
||||
expect(this.signedUrl.length).toBeGreaterThan(0)
|
||||
},
|
||||
)
|
||||
|
||||
Then(
|
||||
'downloading the signed URL returns {string}',
|
||||
async function (this: ContentWorld, expectedContent: string) {
|
||||
const res = await fetch(this.signedUrl)
|
||||
expect(res.ok, `signed download failed: ${res.status}`).toBe(true)
|
||||
const text = await res.text()
|
||||
expect(text).toBe(expectedContent)
|
||||
},
|
||||
)
|
||||
|
||||
When('I strip the signature from the signed URL', function (this: ContentWorld) {
|
||||
const url = new URL(this.signedUrl)
|
||||
url.searchParams.delete('sig')
|
||||
this.signedUrl = url.toString()
|
||||
})
|
||||
|
||||
Then(
|
||||
'fetching the unsigned URL returns a 4xx status',
|
||||
async function (this: ContentWorld) {
|
||||
const res = await fetch(this.signedUrl)
|
||||
expect(res.status, `expected 4xx for unsigned access, got ${res.status}`).toBeGreaterThanOrEqual(400)
|
||||
expect(res.status).toBeLessThan(500)
|
||||
},
|
||||
)
|
||||
Reference in New Issue
Block a user