Allow testers to attach evidence files to a single test case within a specific test run, proving the test was actually executed. Attachments are scoped to the RunCase (per-execution), not the shared case definition. Backend: - runCaseAttachments join table + model (CASCADE on runCase/attachment) - POST/GET /runcaseattachments routes (reuse /attachments download+delete) Frontend: - new "Test record" tab in the run case detail pane with drag-and-drop upload, scoped to reporters; i18n for all 6 locales Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
44 lines
962 B
JavaScript
44 lines
962 B
JavaScript
export async function up(queryInterface, Sequelize) {
|
|
await queryInterface.createTable('runCaseAttachments', {
|
|
id: {
|
|
type: Sequelize.INTEGER,
|
|
primaryKey: true,
|
|
autoIncrement: true,
|
|
},
|
|
runCaseId: {
|
|
type: Sequelize.INTEGER,
|
|
references: {
|
|
model: 'runCases',
|
|
key: 'id',
|
|
},
|
|
onUpdate: 'CASCADE',
|
|
onDelete: 'CASCADE',
|
|
},
|
|
attachmentId: {
|
|
type: Sequelize.INTEGER,
|
|
references: {
|
|
model: 'attachments',
|
|
key: 'id',
|
|
},
|
|
onUpdate: 'CASCADE',
|
|
onDelete: 'CASCADE',
|
|
},
|
|
createdAt: {
|
|
type: Sequelize.DATE,
|
|
allowNull: false,
|
|
},
|
|
updatedAt: {
|
|
type: Sequelize.DATE,
|
|
allowNull: false,
|
|
},
|
|
});
|
|
|
|
await queryInterface.addIndex('runCaseAttachments', ['runCaseId', 'attachmentId'], {
|
|
unique: true,
|
|
});
|
|
}
|
|
|
|
export async function down(queryInterface) {
|
|
await queryInterface.dropTable('runCaseAttachments');
|
|
}
|