diff --git a/server/crashmanager/forms.py b/server/crashmanager/forms.py index d42530bb..ba11914a 100644 --- a/server/crashmanager/forms.py +++ b/server/crashmanager/forms.py @@ -58,7 +58,7 @@ class Meta: "description": "Bug description", "security": "This is a security bug", "security_group": "Security group", - "testcase_filename": "Filename that will be used for the testcase", + "testcase_filename": "Testcase basename (without extension)", "blocks": "Blocks", "dependson": "Depends On", } @@ -89,7 +89,7 @@ class Meta: labels = { "name": "Template name", "comment": "Comment", - "testcase_filename": "Filename that will be used for the testcase", + "testcase_filename": "Testcase basename (without extension)", } widgets = { "name": TextInput(), diff --git a/server/crashmanager/migrations/0021_bugzilla_template_basename.py b/server/crashmanager/migrations/0021_bugzilla_template_basename.py new file mode 100644 index 00000000..50894385 --- /dev/null +++ b/server/crashmanager/migrations/0021_bugzilla_template_basename.py @@ -0,0 +1,20 @@ +from django.db import migrations + + +def strip_template_extensions(apps, schema_editor): + Template = apps.get_model("crashmanager", "BugzillaTemplate") + templates = Template.objects.using(schema_editor.connection.alias) + for template in templates.exclude(testcase_filename="").iterator(): + filename = template.testcase_filename + if "." in filename: + templates.filter(pk=template.pk).update( + testcase_filename=filename.rsplit(".", 1)[0] + ) + + +class Migration(migrations.Migration): + dependencies = [ + ("crashmanager", "0020_alter_bucket_optimizedsignature_and_more"), + ] + + operations = [migrations.RunPython(strip_template_extensions)] diff --git a/server/crashmanager/models.py b/server/crashmanager/models.py index ac009f7b..777be5e0 100644 --- a/server/crashmanager/models.py +++ b/server/crashmanager/models.py @@ -932,6 +932,7 @@ class BugzillaTemplate(models.Model): security = models.BooleanField(blank=False, default=False) security_group = models.TextField(blank=True) comment = models.TextField(blank=True) + # Stores only the basename; attachments use the original testcase extension. testcase_filename = models.TextField(blank=True) blocks = models.TextField(blank=True) dependson = models.TextField(blank=True) diff --git a/server/crashmanager/tests/test_bugs.py b/server/crashmanager/tests/test_bugs.py index 071b669e..2c7c7856 100644 --- a/server/crashmanager/tests/test_bugs.py +++ b/server/crashmanager/tests/test_bugs.py @@ -10,9 +10,13 @@ """ import logging +from importlib import import_module +from types import SimpleNamespace import pytest import requests +from django.apps import apps +from django.db import connection from django.urls import reverse from crashmanager.models import BugzillaTemplate @@ -287,3 +291,23 @@ def test_create_external_bug_comment_simple_get(client, cm): ) LOG.debug(response) assert response.status_code == requests.codes["ok"] + + +@pytest.mark.parametrize( + ("filename", "basename"), + [ + ("testcase.zip", "testcase"), + ("testcase.html", "testcase"), + ("testcase.min.js", "testcase.min"), + ("testcase", "testcase"), + ("", ""), + ], +) +def test_template_basename_migration(cm, filename, basename): + template = cm.create_template() + template.testcase_filename = filename + template.save() + migration = import_module("crashmanager.migrations.0021_bugzilla_template_basename") + migration.strip_template_extensions(apps, SimpleNamespace(connection=connection)) + template.refresh_from_db() + assert template.testcase_filename == basename diff --git a/server/frontend/src/components/Bugs/Comments/PublicationForm.vue b/server/frontend/src/components/Bugs/Comments/PublicationForm.vue index bb123bb5..92857e19 100644 --- a/server/frontend/src/components/Bugs/Comments/PublicationForm.vue +++ b/server/frontend/src/components/Bugs/Comments/PublicationForm.vue @@ -235,7 +235,7 @@ import { defineComponent } from "vue"; import * as api from "../../../api"; import * as bugzillaApi from "../../../bugzilla_api"; import * as HandlebarsHelpers from "../../../handlebars_helpers"; -import { errorParser } from "../../../helpers"; +import { errorParser, parseFilename, buildFilename } from "../../../helpers"; import CrashDataSection from "../CrashDataSection.vue"; import HelpPopover from "../HelpPopover.vue"; import TestCaseSection from "../TestCaseSection.vue"; @@ -395,7 +395,7 @@ export default defineComponent({ return attachmentFilenameExtension; }, filenameWithExtension() { - return this.fileName + "." + this.fileExtension; + return buildFilename(this.fileName, this.fileExtension); }, fileMimetype() { const mimeType = mime.getType(this.filenameWithExtension); @@ -417,6 +417,7 @@ export default defineComponent({ this.provider = this.providers.find((p) => p.id === newVal); }, selectedTemplate(newVal) { + this.newFileName = null; this.template = this.templates.find((t) => t.id === newVal); }, }, @@ -573,19 +574,13 @@ export default defineComponent({ getFileDetails() { let attachmentFilename = ""; let attachmentFilenameExtension = ""; - if (this.entry) { - // extract file name - const splittedAttachmentFilename = this.template?.testcase_filename - ? this.template.testcase_filename - : this.entry.testcase.split("/"); - - const attachmentFilenameAndExtension = - splittedAttachmentFilename[ - splittedAttachmentFilename?.length - 1 - ].split("."); - - attachmentFilename = attachmentFilenameAndExtension[0]; - attachmentFilenameExtension = attachmentFilenameAndExtension[1]; + if (this.entry?.testcase) { + const { basename, extension } = parseFilename( + this.entry.testcase, + this.template?.testcase_filename, + ); + attachmentFilename = basename; + attachmentFilenameExtension = extension; } return { attachmentFilename, attachmentFilenameExtension }; diff --git a/server/frontend/src/components/Bugs/PublicationForm.vue b/server/frontend/src/components/Bugs/PublicationForm.vue index 588ac7da..6e6b809a 100644 --- a/server/frontend/src/components/Bugs/PublicationForm.vue +++ b/server/frontend/src/components/Bugs/PublicationForm.vue @@ -525,16 +525,6 @@ class="form-control" /> -