From 95328826b0f9f789825dd3f6596230388c5e1421 Mon Sep 17 00:00:00 2001 From: Vasyl Ivanchuk Date: Sat, 3 Feb 2024 20:06:16 +0200 Subject: [PATCH] feat: add zkVM checkbox filter to verification page --- .../common/CheckBoxInput.stories.ts | 32 +++++++++++++ .../src/components/common/CheckBoxInput.vue | 46 ++++++++++++++++++ packages/app/src/components/form/FormItem.vue | 2 +- packages/app/src/locales/en.json | 3 +- .../src/views/ContractVerificationView.vue | 33 ++++++++++++- .../components/common/CheckBoxInput.spec.ts | 41 ++++++++++++++++ .../views/ContractVerificationView.spec.ts | 48 ++++++++++++++++++- 7 files changed, 199 insertions(+), 6 deletions(-) create mode 100644 packages/app/src/components/common/CheckBoxInput.stories.ts create mode 100644 packages/app/src/components/common/CheckBoxInput.vue create mode 100644 packages/app/tests/components/common/CheckBoxInput.spec.ts diff --git a/packages/app/src/components/common/CheckBoxInput.stories.ts b/packages/app/src/components/common/CheckBoxInput.stories.ts new file mode 100644 index 0000000000..beeeba7b2a --- /dev/null +++ b/packages/app/src/components/common/CheckBoxInput.stories.ts @@ -0,0 +1,32 @@ +import CheckBoxInput from "./CheckBoxInput.vue"; + +export default { + title: "Common/CheckBoxInput", + component: CheckBoxInput, +}; + +type Args = { + value: boolean; + modelValue: boolean; +}; + +const Template = (args: Args) => ({ + components: { CheckBoxInput }, + setup() { + return { args }; + }, + template: ` + CheckBox Input`, +}); + +export const Checked = Template.bind({}) as unknown as { args: Args }; +Checked.args = { + value: true, + modelValue: true, +}; + +export const Unchecked = Template.bind({}) as unknown as { args: Args }; +Unchecked.args = { + value: false, + modelValue: false, +}; diff --git a/packages/app/src/components/common/CheckBoxInput.vue b/packages/app/src/components/common/CheckBoxInput.vue new file mode 100644 index 0000000000..ac878bbec0 --- /dev/null +++ b/packages/app/src/components/common/CheckBoxInput.vue @@ -0,0 +1,46 @@ + + + + + + + diff --git a/packages/app/src/components/form/FormItem.vue b/packages/app/src/components/form/FormItem.vue index 8e179ae1be..f5a72f24e3 100644 --- a/packages/app/src/components/form/FormItem.vue +++ b/packages/app/src/components/form/FormItem.vue @@ -42,7 +42,7 @@ defineProps({ } .label-inline-block { .form-item-label { - @apply inline-block; + @apply float-left; } } diff --git a/packages/app/src/locales/en.json b/packages/app/src/locales/en.json index ee0c84942a..e4b231daf5 100644 --- a/packages/app/src/locales/en.json +++ b/packages/app/src/locales/en.json @@ -457,7 +457,8 @@ "validation": { "required": "Solc version is required" }, - "error": "Unable to get list of supported Solc versions" + "error": "Unable to get list of supported Solc versions", + "zkVM": "zkVM" }, "zksolcVersion": { "label": "Zksolc Version", diff --git a/packages/app/src/views/ContractVerificationView.vue b/packages/app/src/views/ContractVerificationView.vue index 0e7e8bd339..52f01622f1 100644 --- a/packages/app/src/views/ContractVerificationView.vue +++ b/packages/app/src/views/ContractVerificationView.vue @@ -90,6 +90,7 @@ >{{ t(`contractVerification.form.${selectedZkCompiler.name}Version.details`) }} - + + {{ t("contractVerification.form.solcVersion.zkVM") }} [ }, ]); +const isZkVMSolcCompiler = ref(false); const selectedCompilationType = ref(CompilationTypeOptionsEnum.soliditySingleFile); const isSingleFile = computed(() => [CompilationTypeOptionsEnum.soliditySingleFile, CompilationTypeOptionsEnum.vyperSingleFile].includes( @@ -350,7 +366,16 @@ const selectedZkCompiler = computed(() => { }); const selectedCompiler = computed(() => { const compiler = compilerTypeMap[selectedCompilationType.value].compiler; - return compilerVersions.value[compiler]; + const compilerInfo = compilerVersions.value[compiler]; + if (compiler === CompilerEnum.solc) { + return { + ...compilerInfo, + versions: compilerInfo.versions?.filter((version) => + isZkVMSolcCompiler.value ? version.startsWith(zkVMVersionPrefix) : !version.startsWith(zkVMVersionPrefix) + ), + }; + } + return compilerInfo; }); const selectedZkCompilerVersion = ref( selectedZkCompiler.value.versions[selectedZkCompiler.value.versions.length - 1] || "" @@ -496,6 +521,10 @@ const v$ = useVuelidate( form ); +function onZkVMSelectionChanged() { + selectedCompilerVersion.value = selectedCompiler.value.versions[0] || ""; +} + function onCompilationTypeChange() { selectedZkCompilerVersion.value = selectedZkCompiler.value.versions[0] || ""; selectedCompilerVersion.value = selectedCompiler.value.versions[0] || ""; diff --git a/packages/app/tests/components/common/CheckBoxInput.spec.ts b/packages/app/tests/components/common/CheckBoxInput.spec.ts new file mode 100644 index 0000000000..059c419826 --- /dev/null +++ b/packages/app/tests/components/common/CheckBoxInput.spec.ts @@ -0,0 +1,41 @@ +import { describe, expect, it } from "vitest"; + +import { render } from "@testing-library/vue"; + +import CheckBoxInput from "@/components/common/CheckBoxInput.vue"; + +describe("CheckBoxInput", () => { + it("renders default slot", () => { + const { container } = render(CheckBoxInput, { + slots: { + default: { + template: "CheckBox Input", + }, + }, + props: { + value: true, + }, + }); + expect(container.textContent).toBe("CheckBox Input"); + }); + it("renders checked state correctly", async () => { + const { container } = render(CheckBoxInput, { + props: { + modelValue: true, + value: true, + }, + }); + expect(container.querySelector(".checkbox-input-container")!.classList.contains("checked")).toBe(true); + expect(container.querySelector(".checkbox-input-container input")?.checked).toBe(true); + }); + it("renders unchecked state correctly", async () => { + const { container } = render(CheckBoxInput, { + props: { + modelValue: false, + value: false, + }, + }); + expect(container.querySelector(".checkbox-input-container")!.classList.contains("checked")).toBe(false); + expect(container.querySelector(".checkbox-input-container input")?.checked).toBe(false); + }); +}); diff --git a/packages/app/tests/views/ContractVerificationView.spec.ts b/packages/app/tests/views/ContractVerificationView.spec.ts index 160d4e5117..064dcb4a89 100644 --- a/packages/app/tests/views/ContractVerificationView.spec.ts +++ b/packages/app/tests/views/ContractVerificationView.spec.ts @@ -44,13 +44,11 @@ describe("ContractVerificationView:", () => { en: enUS, }, }); - it("has correct title", async () => { expect(i18n.global.t(routes.find((e) => e.name === "contract-verification")?.meta?.title as string)).toBe( "Smart Contract Verification" ); }); - it("uses contract address from query", async () => { const wrapper = mount(ContractVerificationView, { global: { @@ -113,6 +111,52 @@ describe("ContractVerificationView:", () => { expect(wrapper.find("#sourceCode").exists()).toBe(false); expect(wrapper.find(".multi-file-verification").exists()).toBe(true); }); + it("shows zkVM checkbox by default", async () => { + const wrapper = mount(ContractVerificationView, { + global: { + stubs: ["router-link"], + plugins: [i18n, $testId], + }, + }); + + expect(wrapper.find(".checkbox-input-container").exists()).toBe(true); + }); + it("shows zkVM checkbox when solidity MFV was selected", async () => { + const wrapper = mount(ContractVerificationView, { + global: { + stubs: ["router-link"], + plugins: [i18n, $testId], + }, + }); + + await wrapper.find("#compilerType").trigger("click"); + await wrapper.find(`[aria-labelledby="compilerType"] > li:nth-child(2)`).trigger("click"); + expect(wrapper.find(".checkbox-input-container").exists()).toBe(true); + }); + it("doesn't show zkVM checkbox when vyper single file verification was select", async () => { + const wrapper = mount(ContractVerificationView, { + global: { + stubs: ["router-link"], + plugins: [i18n, $testId], + }, + }); + + await wrapper.find("#compilerType").trigger("click"); + await wrapper.find(`[aria-labelledby="compilerType"] > li:nth-child(3)`).trigger("click"); + expect(wrapper.find(".checkbox-input-container").exists()).toBe(false); + }); + it("doesn't show zkVM checkbox when vyper MFV was select", async () => { + const wrapper = mount(ContractVerificationView, { + global: { + stubs: ["router-link"], + plugins: [i18n, $testId], + }, + }); + + await wrapper.find("#compilerType").trigger("click"); + await wrapper.find(`[aria-labelledby="compilerType"] > li:nth-child(4)`).trigger("click"); + expect(wrapper.find(".checkbox-input-container").exists()).toBe(false); + }); it("shows custom error text", async () => { const mock = vi.spyOn(useContractVerification, "default").mockReturnValue({ ...useContractVerification.default(),