feat(KAN-20): unify dialogs feedback and protect ticket drafts
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import vue from '@vitejs/plugin-vue';
|
||||
import { createServer } from 'vite';
|
||||
import { createSSRApp, h } from 'vue';
|
||||
import { renderToString } from 'vue/server-renderer';
|
||||
|
||||
const server = await createServer({
|
||||
configFile: false,
|
||||
plugins: [vue()],
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': fileURLToPath(new URL('../../resources/js', import.meta.url)),
|
||||
},
|
||||
},
|
||||
server: { middlewareMode: true, hmr: false, watch: null },
|
||||
appType: 'custom',
|
||||
});
|
||||
|
||||
try {
|
||||
const { isFormNetworkFailure, matchesFormRequest, formRequestHeader } =
|
||||
await server.ssrLoadModule('/resources/js/lib/form-feedback.ts');
|
||||
const config = { headers: { [formRequestHeader]: 'submission-a' } };
|
||||
for (const code of ['ERR_NETWORK', 'ECONNABORTED', 'ETIMEDOUT']) {
|
||||
assert.equal(
|
||||
isFormNetworkFailure(
|
||||
{ isAxiosError: true, code, config },
|
||||
'submission-a',
|
||||
),
|
||||
true,
|
||||
);
|
||||
}
|
||||
for (const error of [
|
||||
null,
|
||||
new Error('Render failed'),
|
||||
{ code: 'ERR_NETWORK', config },
|
||||
{ isAxiosError: true, code: 'ERR_CANCELED', config },
|
||||
{
|
||||
isAxiosError: true,
|
||||
code: 'ERR_NETWORK',
|
||||
config,
|
||||
response: { status: 500 },
|
||||
},
|
||||
{ isAxiosError: true, code: 'ERR_NETWORK', config: {} },
|
||||
]) {
|
||||
assert.equal(isFormNetworkFailure(error, 'submission-a'), false);
|
||||
}
|
||||
assert.equal(
|
||||
isFormNetworkFailure(
|
||||
{ isAxiosError: true, code: 'ERR_NETWORK', config },
|
||||
'submission-b',
|
||||
),
|
||||
false,
|
||||
);
|
||||
assert.equal(matchesFormRequest(config, null), false);
|
||||
assert.equal(matchesFormRequest(config, 'submission-a'), true);
|
||||
assert.equal(matchesFormRequest(undefined, 'submission-a'), false);
|
||||
|
||||
const { createLocalization } = await server.ssrLoadModule(
|
||||
'/resources/js/lib/localization.ts',
|
||||
);
|
||||
const { en } = await server.ssrLoadModule('/resources/js/locales/en.ts');
|
||||
const { default: FeedbackState } = await server.ssrLoadModule(
|
||||
'/resources/js/components/FeedbackState.vue',
|
||||
);
|
||||
const { default: FormFeedback } = await server.ssrLoadModule(
|
||||
'/resources/js/components/FormFeedback.vue',
|
||||
);
|
||||
const { default: InputError } = await server.ssrLoadModule(
|
||||
'/resources/js/components/InputError.vue',
|
||||
);
|
||||
const localization = createLocalization(
|
||||
{ locale: 'de' },
|
||||
{
|
||||
de: {
|
||||
...en,
|
||||
'common.retry': 'Erneut versuchen',
|
||||
'feedback.empty': 'Noch keine Einträge',
|
||||
},
|
||||
},
|
||||
);
|
||||
const render = (component, props) =>
|
||||
renderToString(
|
||||
createSSRApp({ render: () => h(component, props) }).use(
|
||||
localization,
|
||||
),
|
||||
);
|
||||
assert.match(
|
||||
await render(FeedbackState, { state: 'empty' }),
|
||||
/Noch keine Einträge/,
|
||||
);
|
||||
const loading = await render(FormFeedback, { state: 'loading' });
|
||||
assert.match(loading, /role="status"/);
|
||||
assert.match(loading, /aria-busy="true"/);
|
||||
assert.match(loading, /motion-reduce:animate-none/);
|
||||
assert.doesNotMatch(loading, /<button/);
|
||||
const validation = await render(FormFeedback, { state: 'validation' });
|
||||
assert.match(validation, /role="alert"/);
|
||||
assert.match(validation, /Check your entries/);
|
||||
assert.doesNotMatch(validation, /<button/);
|
||||
for (const state of ['network', 'server', 'cancelled']) {
|
||||
const html = await render(FormFeedback, { state });
|
||||
assert.match(html, /Erneut versuchen/);
|
||||
assert.match(html, /type="button"/);
|
||||
assert.match(html, /role="alert"/);
|
||||
}
|
||||
assert.match(
|
||||
await render(FormFeedback, { state: 'network' }),
|
||||
/Connection interrupted/,
|
||||
);
|
||||
assert.match(
|
||||
await render(FormFeedback, { state: 'server' }),
|
||||
/unexpected response/,
|
||||
);
|
||||
assert.match(
|
||||
await render(FormFeedback, { state: 'success' }),
|
||||
/Changes saved/,
|
||||
);
|
||||
assert.doesNotMatch(await render(FormFeedback, { state: 'idle' }), /role=/);
|
||||
const fieldError = await render(InputError, {
|
||||
message: '<script>alert(1)</script>',
|
||||
});
|
||||
assert.match(fieldError, /role="alert"/);
|
||||
assert.match(fieldError, /text-destructive/);
|
||||
assert.doesNotMatch(fieldError, /<script>/);
|
||||
console.log('Form feedback behavior checks passed.');
|
||||
} finally {
|
||||
await server.close();
|
||||
}
|
||||
Reference in New Issue
Block a user