Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

N21-2052 adjust ctl autocomplete #3313

Merged
merged 30 commits into from
Jul 11, 2024
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
ea07696
N21-2052 generate api, adds baseUrl and change autocomplete wip
arnegns Jul 3, 2024
3978a27
added check for valid url & hide "no data" when url is inputted
GordonNicholasCap Jul 3, 2024
16f5116
Merge branch 'refs/heads/main' into N21-2052-ctl-url-insertion
arnegns Jul 3, 2024
b8613a5
Merge branch 'refs/heads/main' into N21-2052-ctl-url-insertion
arnegns Jul 3, 2024
26820ca
N21-2052 some logic
arnegns Jul 3, 2024
99c51eb
N21-2052 fixes escaping
arnegns Jul 4, 2024
c1ed9ce
N21-2052 fixes test
arnegns Jul 4, 2024
92f7efa
N21-2052 changes ExternalToolSelectionRow.vue to script setup
arnegns Jul 4, 2024
cd373b2
N21-2052 some changes
arnegns Jul 4, 2024
9a040a8
N21-2052 adds clipboard logic
arnegns Jul 4, 2024
6938535
N21-2052 fixes linter error
arnegns Jul 4, 2024
8872d6d
fixed settings still showing when box is cleared, minor cleanup
GordonNicholasCap Jul 4, 2024
1c26507
moved code for url into composable, added query param extractor
GordonNicholasCap Jul 4, 2024
eaa0728
added hint below combobox, changed paste url icon
GordonNicholasCap Jul 5, 2024
e22917c
adjusted valid url regex, fixed minor bugs in composable
GordonNicholasCap Jul 5, 2024
b538fa6
wip unit tests for configurator & composable
GordonNicholasCap Jul 5, 2024
e7368bb
full unit tests for composable
GordonNicholasCap Jul 8, 2024
abe2ccb
refactored script -> script setup, fixed missing baseUrl
GordonNicholasCap Jul 8, 2024
feb15a2
cleanup unit tests, skip tests involving combobox's selection menu
GordonNicholasCap Jul 9, 2024
7b54bc9
added proper error handling for clipboard, adjusted code for checking…
GordonNicholasCap Jul 9, 2024
4109dcd
Merge branch 'refs/heads/main' into N21-2052-ctl-url-insertion
GordonNicholasCap Jul 9, 2024
c73dc00
fixed tests
GordonNicholasCap Jul 9, 2024
73806b5
make search box testable
MarvinOehlerkingCap Jul 10, 2024
e204700
N21-2052 refactored composable unit tests to be simpler
GordonNicholasCap Jul 10, 2024
5439fa4
N21-2052 renamed comboboxRef, added test for selection list filter
GordonNicholasCap Jul 10, 2024
a9b34c5
remove v-if from slot
MarvinOehlerkingCap Jul 11, 2024
5e58111
change order of execution for paste-icon
MarvinOehlerkingCap Jul 11, 2024
f2cfc93
minor adjustments, fixed typos
GordonNicholasCap Jul 11, 2024
8c9716b
Merge branch 'main' into N21-2052-ctl-url-insertion
GordonNicholasCap Jul 11, 2024
9bf5b83
fix focus and accessibility for past-icon
MarvinOehlerkingCap Jul 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import * as useExternalToolUtilsComposable from "@/composables/external-tool-mappings.composable";
import { SchoolExternalTool } from "@/store/external-tool";
import {
SchoolExternalTool,
ToolParameter,
ToolParameterLocation,
} from "@/store/external-tool";
import { BusinessError } from "@/store/types/commons";
import {
schoolExternalToolConfigurationTemplateFactory,
schoolExternalToolFactory,
toolParameterFactory,
} from "@@/tests/test-utils/factory";
import {
createTestingI18n,
Expand All @@ -16,6 +21,7 @@ import {
import { mount, VueWrapper } from "@vue/test-utils";
import { VBtn } from "vuetify/lib/components/index.mjs";
import ExternalToolConfigurator from "./ExternalToolConfigurator.vue";
import { DeepPartial } from "fishery";

describe("ExternalToolConfigurator", () => {
jest
Expand Down Expand Up @@ -47,7 +53,8 @@ describe("ExternalToolConfigurator", () => {
jest.clearAllMocks();
});

describe("autocomplete", () => {
// TODO: new tests for combobox
MarvinOehlerkingCap marked this conversation as resolved.
Show resolved Hide resolved
describe("combobox", () => {
describe("when selecting a new configuration", () => {
const setup = () => {
const template = schoolExternalToolConfigurationTemplateFactory.build({
Expand Down Expand Up @@ -129,44 +136,235 @@ describe("ExternalToolConfigurator", () => {
it("should display the edited tool in the selection", async () => {
const { wrapper, template } = setup();

const selectionRow = wrapper.find(".v-autocomplete .v-list-item-title");
const selectionRow = wrapper.find(".v-combobox .v-list-item-title");

expect(selectionRow.text()).toEqual(template.name);
});
});
});

describe("cancel button", () => {
describe("when clicking the cancel button", () => {
it("should emit the cancel event", async () => {
describe("when inputting an url which matches the baseUrl of a tool", () => {
const setup = () => {
const templates = [];
templates.push(schoolExternalToolConfigurationTemplateFactory.build());
templates.push(schoolExternalToolConfigurationTemplateFactory.build());

const { wrapper } = getWrapper({
templates:
schoolExternalToolConfigurationTemplateFactory.buildList(1),
templates: templates,
});

await wrapper
.findComponent<typeof VBtn>('[data-testId="cancel-button"]')
.trigger("click");
const openSelect = async (wrapper: VueWrapper) => {
await wrapper
.find('[data-testId="configuration-select"]')
.trigger("click");
};

return {
wrapper,
templates,
openSelect,
};
};

const getSelectionItems = (wrapper: VueWrapper) => {
return [];
};

it("should display only the matched tool in the selection", async () => {
const { wrapper, templates, openSelect } = setup();
await openSelect(wrapper);

const selectInputField = wrapper.get("input");
const inputUrl = templates[0].baseUrl;
await selectInputField.setValue(inputUrl);

const selectionItems = getSelectionItems(wrapper);

expect(wrapper.emitted("cancel")).toBeDefined();
expect(selectionItems).toEqual(1);
// TODO: precise baseURL expects
});
});
});

describe("save button", () => {
describe("when clicking the save button", () => {
it("should emit the save event", async () => {
describe("when inputting an url with path params", () => {
const createBaseUrlWithPathParams = (
template: ExternalToolConfigurationTemplate
): string => {
let url = template.baseUrl;
template.parameters.forEach((parameter) => {
url += `/:${parameter.name}`;
});
url += "/";
return url;
};

const setup = () => {
const pathParams = [];
const pathParamConfig: DeepPartial<ToolParameter> = {
location: ToolParameterLocation.PATH,
};
pathParams.push(toolParameterFactory.build(pathParamConfig));
pathParams.push(toolParameterFactory.build(pathParamConfig));

const templates = [];
const templateWithParam =
schoolExternalToolConfigurationTemplateFactory.build({
parameters: pathParams,
});
templateWithParam.baseUrl =
createBaseUrlWithPathParams(templateWithParam);
templates.push(templateWithParam);
templates.push(schoolExternalToolConfigurationTemplateFactory.build());

const { wrapper } = getWrapper({
templates:
schoolExternalToolConfigurationTemplateFactory.buildList(1),
templates: templates,
configuration: schoolExternalToolFactory.build(),
});

await wrapper
.findComponent<typeof VBtn>('[data-testId="save-button"]')
.trigger("click");
const openSelect = async (wrapper: VueWrapper) => {
await wrapper
.find('[data-testId="configuration-select"]')
.trigger("click");
};

return {
wrapper,
templates,
openSelect,
};
};

it("should set path parameters values from inputted url in the configuration fields", async () => {
const { wrapper, templates, openSelect } = setup();
await openSelect(wrapper);

const selectInputField = wrapper.get("input");
const testPathParams = ["test-2", "test-1"];
const baseUrlParts = templates[0].baseUrl.split("/");
const inputUrlParts: string[] = [];
baseUrlParts.forEach((part) => {
let inputPart = part;
if (part.startsWith(":")) {
inputPart = testPathParams.pop() ?? "test";
}
inputUrlParts.push(inputPart);
});
const inputUrl = inputUrlParts.join("/");
await selectInputField.setValue(inputUrl);

// somehow click on the selection?

expect(wrapper.emitted("save")).toBeDefined();
const configFields = wrapper.findAll(
'[data-testId="configuration-field"]'
);
configFields.forEach((field) => {
const input = field.find("v-field__input");
expect(input.text()).toEqual("test-1");
});
});
});

describe("when inputting an url with query parameters", () => {
const setup = () => {
const queryParams = [];
const queryParamConfig: DeepPartial<ToolParameter> = {
location: ToolParameterLocation.QUERY,
};
queryParams.push(toolParameterFactory.build(queryParamConfig));

const templates = [];
templates.push(
schoolExternalToolConfigurationTemplateFactory.build({
parameters: queryParams,
})
);
templates.push(schoolExternalToolConfigurationTemplateFactory.build());

const { wrapper } = getWrapper({
templates: templates,
configuration: schoolExternalToolFactory.build(),
});

const openSelect = async (wrapper: VueWrapper) => {
await wrapper
.find('[data-testId="configuration-select"]')
.trigger("click");
};

const createInputUrlFromTemplate = (
template: ExternalToolConfigurationTemplate
) => {
const testPathParams = ["test-2", "test-1"];
let queryString = "";
template.parameters.forEach((parameter, index) => {
if (index > 0) {
queryString += "&";
}
queryString += `${parameter.name}=${testPathParams[index]}`;
});
return template.baseUrl + "?" + queryString;
};

return {
wrapper,
templates,
openSelect,
createInputUrlFromTemplate,
};
};

it("should set query parameters values from inputted url in the configuration fields", async () => {
const { wrapper, templates, openSelect, createInputUrlFromTemplate } =
setup();
await openSelect(wrapper);

const inputUrl = createInputUrlFromTemplate(templates[0]);

const selectInputField = wrapper.get("input");
await selectInputField.setValue(inputUrl);

// somehow click on the selection?

const configFields = wrapper.findAll(
'[data-testId="configuration-field"]'
);
configFields.forEach((field) => {
const input = field.find("v-field__input");
expect(input.text()).toEqual("test-1");
});
});
});

describe("cancel button", () => {
describe("when clicking the cancel button", () => {
it("should emit the cancel event", async () => {
const { wrapper } = getWrapper({
templates:
schoolExternalToolConfigurationTemplateFactory.buildList(1),
});

await wrapper
.findComponent<typeof VBtn>('[data-testId="cancel-button"]')
.trigger("click");

expect(wrapper.emitted("cancel")).toBeDefined();
});
});
});

describe("save button", () => {
describe("when clicking the save button", () => {
it("should emit the save event", async () => {
const { wrapper } = getWrapper({
templates:
schoolExternalToolConfigurationTemplateFactory.buildList(1),
configuration: schoolExternalToolFactory.build(),
});

await wrapper
.findComponent<typeof VBtn>('[data-testId="save-button"]')
.trigger("click");

expect(wrapper.emitted("save")).toBeDefined();
});
});
});
});
Expand Down
Loading
Loading