feat: track purchase site URL for new components
- New nullable purchase_url column on components - Store/update validators accept an optional purchaseUrl (must be a valid absolute URL with a protocol when provided) - components/create.vue: NewPartSearch import now also fills purchaseUrl from the scraped part's source URL (pc-builder.io product page); the field remains manually editable for second-hand parts entered by hand - components/edit.vue: purchaseUrl is editable after creation - components/show.vue: displays the purchase site as a clickable link when present - 4 new functional tests: create with/without a purchase URL, invalid URL rejected (asserts the Inertia inputErrorsBag flash, not a raw 422 - content negotiation only returns JSON for XHR/API-style requests), and updating an existing component's purchase URL
This commit is contained in:
1 parent
497ae797ca
commit
4174d92711
10 files changed
+174
-6
No files matched your search
@@ -102,3 +102,97 @@ test.group('Components authorization (IDOR)', () => {
|
||||
assert.isNotNull(stillExists)
|
||||
})
|
||||
})
|
||||
|
||||
test.group('Components purchase URL', () => {
|
||||
test('a component can be created with a purchase site URL', async ({ client, assert }) => {
|
||||
const user = await createUser('purchase-url-a@example.com')
|
||||
const type = await createType('RAM-purchase-1')
|
||||
|
||||
const response = await client
|
||||
.post('/components')
|
||||
.loginAs(user)
|
||||
.withCsrfToken()
|
||||
.redirects(0)
|
||||
.json({
|
||||
name: 'New GPU',
|
||||
price: 599.99,
|
||||
typeId: type.id,
|
||||
purchaseDate: DateTime.now().toFormat('yyyy-MM-dd'),
|
||||
purchaseUrl: 'https://fr.pc-builder.io/gpu/example-p1',
|
||||
quantity: 1,
|
||||
})
|
||||
|
||||
response.assertStatus(302)
|
||||
const component = await Component.query().where('userId', user.id).firstOrFail()
|
||||
assert.equal(component.purchaseUrl, 'https://fr.pc-builder.io/gpu/example-p1')
|
||||
})
|
||||
|
||||
test('a component can be created without a purchase site URL', async ({ client, assert }) => {
|
||||
const user = await createUser('purchase-url-b@example.com')
|
||||
const type = await createType('RAM-purchase-2')
|
||||
|
||||
const response = await client
|
||||
.post('/components')
|
||||
.loginAs(user)
|
||||
.withCsrfToken()
|
||||
.redirects(0)
|
||||
.json({
|
||||
name: 'Used RAM stick',
|
||||
price: 20,
|
||||
typeId: type.id,
|
||||
purchaseDate: DateTime.now().toFormat('yyyy-MM-dd'),
|
||||
quantity: 1,
|
||||
})
|
||||
|
||||
response.assertStatus(302)
|
||||
const component = await Component.query().where('userId', user.id).firstOrFail()
|
||||
assert.isNull(component.purchaseUrl)
|
||||
})
|
||||
|
||||
test('an invalid purchase URL is rejected', async ({ client, assert }) => {
|
||||
const user = await createUser('purchase-url-c@example.com')
|
||||
const type = await createType('RAM-purchase-3')
|
||||
|
||||
const response = await client
|
||||
.post('/components')
|
||||
.loginAs(user)
|
||||
.withCsrfToken()
|
||||
.redirects(0)
|
||||
.json({
|
||||
name: 'Suspicious component',
|
||||
price: 20,
|
||||
typeId: type.id,
|
||||
purchaseDate: DateTime.now().toFormat('yyyy-MM-dd'),
|
||||
purchaseUrl: 'not-a-url',
|
||||
quantity: 1,
|
||||
})
|
||||
|
||||
response.assertStatus(302)
|
||||
assert.property(response.flashMessage('inputErrorsBag'), 'purchaseUrl')
|
||||
const created = await Component.query().where('userId', user.id).first()
|
||||
assert.isNull(created)
|
||||
})
|
||||
|
||||
test('the purchase URL can be updated on an existing component', async ({ client, assert }) => {
|
||||
const owner = await createUser('purchase-url-d@example.com')
|
||||
const type = await createType('RAM-purchase-4')
|
||||
const component = await createComponent(owner.id, type.id)
|
||||
|
||||
const response = await client
|
||||
.put(`/components/${component.id}`)
|
||||
.loginAs(owner)
|
||||
.withCsrfToken()
|
||||
.redirects(0)
|
||||
.json({
|
||||
name: component.name,
|
||||
price: component.price,
|
||||
typeId: type.id,
|
||||
purchaseDate: DateTime.now().toFormat('yyyy-MM-dd'),
|
||||
purchaseUrl: 'https://fr.pc-builder.io/cpu/example-p2',
|
||||
})
|
||||
|
||||
response.assertStatus(302)
|
||||
await component.refresh()
|
||||
assert.equal(component.purchaseUrl, 'https://fr.pc-builder.io/cpu/example-p2')
|
||||
})
|
||||
})
|
||||
Reference in new issue
Block a user