feat: simplify ticket links to action and ticket (KAN-12)
This commit is contained in:
@@ -5,7 +5,7 @@ import tailwind from '@tailwindcss/vite';
|
||||
import vue from '@vitejs/plugin-vue';
|
||||
import { createInertiaApp } from '@inertiajs/vue3';
|
||||
import { createServer } from 'vite';
|
||||
import { createSSRApp, h } from 'vue';
|
||||
import { createSSRApp, h, reactive, ref } from 'vue';
|
||||
import { renderToString } from 'vue/server-renderer';
|
||||
|
||||
const serve = process.argv.includes('--serve');
|
||||
@@ -463,6 +463,40 @@ if (serve) {
|
||||
);
|
||||
} else {
|
||||
try {
|
||||
const { useTicketLinkActions } = await server.ssrLoadModule(
|
||||
'/resources/js/composables/useTicketLinkActions.ts',
|
||||
);
|
||||
const linkTypes = ref([
|
||||
{ id: 1, label: 'Blocks', counterpart_label: 'Blocked by' },
|
||||
{ id: 2, label: 'Relates to', counterpart_label: 'Relates to' },
|
||||
]);
|
||||
const linkForm = reactive({
|
||||
ticket_link_type_id: 1,
|
||||
link_direction: 'source',
|
||||
linked_ticket_id: 41,
|
||||
});
|
||||
const { actions, selectedAction, selectedActionLabel } =
|
||||
useTicketLinkActions(linkTypes, linkForm);
|
||||
assert.deepEqual(
|
||||
actions.value.map((action) => action.label),
|
||||
['Blocks', 'Blocked by', 'Relates to'],
|
||||
);
|
||||
assert.equal(selectedActionLabel.value, 'Blocks');
|
||||
selectedAction.value = '1:counterpart';
|
||||
assert.equal(selectedActionLabel.value, 'Blocked by');
|
||||
assert.deepEqual(
|
||||
{ ...linkForm },
|
||||
{
|
||||
ticket_link_type_id: 1,
|
||||
link_direction: 'counterpart',
|
||||
linked_ticket_id: 41,
|
||||
},
|
||||
);
|
||||
selectedAction.value = '2:source';
|
||||
assert.equal(linkForm.ticket_link_type_id, 2);
|
||||
assert.equal(linkForm.link_direction, 'source');
|
||||
selectedAction.value = 'unknown';
|
||||
assert.equal(selectedActionLabel.value, 'Relates to');
|
||||
const { createLocalization } = await server.ssrLoadModule(
|
||||
'/resources/js/lib/localization.ts',
|
||||
);
|
||||
@@ -491,8 +525,24 @@ if (serve) {
|
||||
return result.body.split('id="main-content"')[1];
|
||||
};
|
||||
const html = await render();
|
||||
assert.ok(html.includes('id="link_direction"'));
|
||||
assert.ok(!html.includes('id="link_direction"'));
|
||||
assert.ok(html.includes('Blocked by'));
|
||||
const linkFields = [
|
||||
...html.matchAll(/<fieldset\b[^>]*>[\s\S]*?<\/fieldset>/g),
|
||||
].find(([fieldset]) =>
|
||||
fieldset.includes('id="ticket_link_type_id"'),
|
||||
)?.[0];
|
||||
assert.ok(linkFields);
|
||||
assert.equal((linkFields.match(/<select\b/g) ?? []).length, 2);
|
||||
assert.match(
|
||||
linkFields,
|
||||
/<option value="1:source"[^>]*>Blocks<\/option>/,
|
||||
);
|
||||
assert.match(
|
||||
linkFields,
|
||||
/<option value="1:counterpart"[^>]*>Blocked by<\/option>/,
|
||||
);
|
||||
assert.doesNotMatch(linkFields, /Blocks \/ Blocked by/);
|
||||
for (const text of [
|
||||
ticket.title,
|
||||
'Keep every existing ticket action available.',
|
||||
@@ -570,9 +620,9 @@ if (serve) {
|
||||
/<a(?=[^>]*href="https:\/\/git\.example\.test\/Engineering\/platform\/pulls\/12")(?=[^>]*target="_blank")(?=[^>]*rel="noopener noreferrer")[^>]*>/,
|
||||
);
|
||||
assert.match(html, /Save link/);
|
||||
assert.match(html, /Outgoing/);
|
||||
assert.doesNotMatch(html, /Outgoing/);
|
||||
const incoming = await render('?incoming');
|
||||
assert.match(incoming, /Incoming/);
|
||||
assert.doesNotMatch(incoming, /Incoming/);
|
||||
assert.match(incoming, /Blocked by/);
|
||||
assert.match(await render('?noTypes'), /No link types are configured/);
|
||||
assert.match(
|
||||
|
||||
@@ -41,8 +41,6 @@ try {
|
||||
'Platform delivery',
|
||||
'Child tickets',
|
||||
'Nested child with a long title that must wrap on mobile',
|
||||
'Incoming',
|
||||
'Blocked by',
|
||||
]) {
|
||||
assert.equal(
|
||||
await section()
|
||||
@@ -52,6 +50,13 @@ try {
|
||||
text,
|
||||
);
|
||||
}
|
||||
assert.equal(
|
||||
await section()
|
||||
.locator('[data-ticket-link]')
|
||||
.getByText('Blocked by', { exact: true })
|
||||
.isVisible(),
|
||||
true,
|
||||
);
|
||||
const collapse = section().getByRole('button', {
|
||||
name: 'Collapse children of ENG-41',
|
||||
});
|
||||
@@ -68,16 +73,7 @@ try {
|
||||
);
|
||||
await page.keyboard.press('Space');
|
||||
assert.equal(await collapse.getAttribute('aria-expanded'), 'true');
|
||||
await control('Link type').focus();
|
||||
await page.keyboard.press('Tab');
|
||||
assert.equal(
|
||||
await control('This ticket').evaluate(
|
||||
(el) =>
|
||||
el === document.activeElement &&
|
||||
el.matches(':focus-visible'),
|
||||
),
|
||||
true,
|
||||
);
|
||||
await control('Action').focus();
|
||||
await page.keyboard.press('Tab');
|
||||
assert.equal(
|
||||
await control('Linked ticket').evaluate(
|
||||
@@ -130,7 +126,10 @@ try {
|
||||
link_direction: 'source',
|
||||
linked_ticket_id: 41,
|
||||
});
|
||||
await section().getByText('Outgoing', { exact: true }).waitFor();
|
||||
await section()
|
||||
.locator('[data-ticket-link]')
|
||||
.getByText('Blocks', { exact: true })
|
||||
.waitFor();
|
||||
await page.waitForFunction(
|
||||
() => document.querySelector('#linked_ticket_id')?.value === '',
|
||||
);
|
||||
@@ -152,11 +151,10 @@ try {
|
||||
);
|
||||
|
||||
await visit('?noLinks');
|
||||
await control('This ticket').selectOption('counterpart');
|
||||
await control('Action').selectOption('1:counterpart');
|
||||
await control('Linked ticket').selectOption('41');
|
||||
await section()
|
||||
.locator('form')
|
||||
.last()
|
||||
.locator('p[aria-live="polite"]')
|
||||
.getByText('Blocked by', { exact: true })
|
||||
.waitFor();
|
||||
request = page.waitForRequest(
|
||||
@@ -168,7 +166,10 @@ try {
|
||||
link_direction: 'counterpart',
|
||||
linked_ticket_id: 41,
|
||||
});
|
||||
await section().getByText('Incoming', { exact: true }).waitFor();
|
||||
await section()
|
||||
.locator('[data-ticket-link]')
|
||||
.getByText('Blocked by', { exact: true })
|
||||
.waitFor();
|
||||
|
||||
await visit('?rejectLink');
|
||||
await control('Linked ticket').selectOption('41');
|
||||
@@ -177,7 +178,7 @@ try {
|
||||
.getByText('Choose another ticket.', { exact: true })
|
||||
.waitFor();
|
||||
assert.equal(await control('Linked ticket').inputValue(), '41');
|
||||
for (const label of ['Link type', 'Linked ticket']) {
|
||||
for (const label of ['Action', 'Linked ticket']) {
|
||||
assert.equal(await control(label).getAttribute('aria-invalid'), 'true');
|
||||
}
|
||||
await page.route('**/tickets/42/links', (route) => route.abort('failed'));
|
||||
|
||||
Reference in New Issue
Block a user