Skip to content

Commit

Permalink
Merge pull request #265 from getodk/fix/post-060-wfp
Browse files Browse the repository at this point in the history
Fix: Web Forms Preview demo form links
  • Loading branch information
eyelidlessness authored Dec 16, 2024
2 parents 0acbbc2 + b0f19c3 commit dfc6c70
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 19 deletions.
20 changes: 15 additions & 5 deletions packages/common/src/fixtures/import-glob-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,16 @@ if (IS_NODE_RUNTIME) {

type ImportMetaGlobURLRecord = Readonly<Record<string, string>>;

export type ImportMetaGlobLoader = (this: void) => Promise<string>;
export type GlobFixtureLoader = (this: void) => Promise<string>;

export type GlobLoaderEntry = readonly [absolutePath: string, loader: ImportMetaGlobLoader];
export interface GlobFixture {
readonly url: URL;
readonly load: GlobFixtureLoader;
}

export type GlobFixtureEntry = readonly [absolutePath: string, loader: GlobFixture];

const globLoader = (globURL: string): ImportMetaGlobLoader => {
const globFixtureLoader = (globURL: string): GlobFixtureLoader => {
return async () => {
const response = await fetchGlobURL(globURL);

Expand All @@ -49,12 +54,17 @@ const globLoader = (globURL: string): ImportMetaGlobLoader => {
export const toGlobLoaderEntries = (
importMeta: ImportMeta,
globObject: ImportMetaGlobURLRecord
): readonly GlobLoaderEntry[] => {
): readonly GlobFixtureEntry[] => {
const parentPathURL = new URL('./', importMeta.url);

return Object.entries(globObject).map(([relativePath, value]) => {
const { pathname: absolutePath } = new URL(relativePath, parentPathURL);
const fixtureAssetURL = new URL(value, import.meta.url);
const fixture: GlobFixture = {
url: fixtureAssetURL,
load: globFixtureLoader(value),
};

return [absolutePath, globLoader(value)];
return [absolutePath, fixture];
});
};
6 changes: 3 additions & 3 deletions packages/common/src/fixtures/xform-attachments.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { UpsertableMap } from '../lib/collections/UpsertableMap.ts';
import { UnreachableError } from '../lib/error/UnreachableError.ts';
import type { ImportMetaGlobLoader } from './import-glob-helper.ts';
import type { GlobFixtureLoader } from './import-glob-helper.ts';
import { toGlobLoaderEntries } from './import-glob-helper.ts';

/**
Expand Down Expand Up @@ -60,7 +60,7 @@ export class XFormAttachmentFixture {

constructor(
readonly absolutePath: string,
readonly load: ImportMetaGlobLoader
readonly load: GlobFixtureLoader
) {
const fileName = getFileName(absolutePath);
const fileExtension = getFileExtension(fileName);
Expand Down Expand Up @@ -97,7 +97,7 @@ type XFormAttachmentFixtureEntry = readonly [absolutePath: string, fixture: XFor
type XFormAttachmentFixtureEntries = readonly XFormAttachmentFixtureEntry[];

const xformAttachmentFixtureEntries: XFormAttachmentFixtureEntries =
xformAttachmentFixtureLoaderEntries.map(([absolutePath, load]) => {
xformAttachmentFixtureLoaderEntries.map(([absolutePath, { load }]) => {
const fixture = new XFormAttachmentFixture(absolutePath, load);

return [absolutePath, fixture];
Expand Down
15 changes: 5 additions & 10 deletions packages/common/src/fixtures/xforms.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { JRResourceService } from '../jr-resources/JRResourceService.ts';
import type { JRResourceURL } from '../jr-resources/JRResourceURL.ts';
import { UpsertableMap } from '../lib/collections/UpsertableMap.ts';
import type { GlobFixture } from './import-glob-helper.ts';
import { toGlobLoaderEntries } from './import-glob-helper.ts';

type XFormResourceType = 'local' | 'remote';
Expand Down Expand Up @@ -92,12 +93,8 @@ const getNoopResourceService: ResourceServiceFactory = () => {
};

export class XFormResource<Type extends XFormResourceType> {
static forLocalFixture(
localPath: string,
resourceURL: URL,
loadXML?: LoadXFormXML
): XFormResource<'local'> {
return new XFormResource('local', resourceURL, loadXML ?? xformURLLoader(resourceURL), {
static forLocalFixture(localPath: string, fixture: GlobFixture): XFormResource<'local'> {
return new XFormResource('local', fixture.url, fixture.load, {
category: localFixtureDirectoryCategory(localPath),
localPath,
identifier: pathToFileName(localPath),
Expand Down Expand Up @@ -168,10 +165,8 @@ const xformFixtureLoaderEntries = toGlobLoaderEntries(
export type XFormFixture = XFormResource<'local'>;

const buildXFormFixtures = (): readonly XFormFixture[] => {
return xformFixtureLoaderEntries.map(([path, loadXML]) => {
const resourceURL = new URL(path, SELF_URL);

return XFormResource.forLocalFixture(path, resourceURL, loadXML);
return xformFixtureLoaderEntries.map(([path, fixture]) => {
return XFormResource.forLocalFixture(path, fixture);
});
};

Expand Down
26 changes: 26 additions & 0 deletions packages/web-forms/e2e/build/wf-preview.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { expect, test } from '@playwright/test';

test('Web Forms Preview: demo forms load', async ({ context, page }) => {
await page.goto('http://localhost:5174/');

const formPreviewLinks = await page.locator('.form-preview-link').all();

expect(formPreviewLinks.length).toBeGreaterThan(0);

for await (const link of formPreviewLinks) {
const [previewPage] = await Promise.all([context.waitForEvent('page'), link.click()]);

await previewPage.waitForSelector(
'.form-initialization-status.error, .form-initialization-status.ready',
{
state: 'attached',
}
);

const [failureDialog] = await previewPage.locator('.form-load-failure-dialog').all();

expect(failureDialog).toBeUndefined();

await previewPage.close();
}
});
13 changes: 13 additions & 0 deletions packages/web-forms/src/components/OdkWebForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,15 @@ watchEffect(() => {
applicable for usage of a given tag.
-->
<template>
<div
:class="{
'form-initialization-status': true,
loading: odkForm == null && initializeFormError == null,
error: initializeFormError != null,
ready: odkForm != null,
}"
/>

<template v-if="initializeFormError != null">
<FormLoadFailureDialog
severity="error"
Expand Down Expand Up @@ -133,6 +142,10 @@ watchEffect(() => {
<style scoped lang="scss">
@import 'primeflex/core/_variables.scss';

.form-initialization-status {
display: none;
}

.odk-form {
width: 100%;
color: var(--text-color);
Expand Down
2 changes: 1 addition & 1 deletion packages/web-forms/src/demo/DemoForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const formXls = computed(() => {
<slot name="description" />
</p>
<div class="actions">
<RouterLink :to="`/form?url=${formXml}`" target="_blank">
<RouterLink :to="`/form?url=${formXml}`" target="_blank" class="form-preview-link">
<PrimeButton class="preview-button" label="View Form" icon="icon-remove_red_eye" />
</RouterLink>
<a :href="formXls">
Expand Down

0 comments on commit dfc6c70

Please sign in to comment.