Skip to content

Commit

Permalink
wip #29 tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
ComLock committed Apr 11, 2024
1 parent 4cc14dc commit 5e1e4ed
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 84 deletions.
31 changes: 25 additions & 6 deletions docs/mock-xp.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,44 @@ Let's write a test for the following controller:
include::{sourcedir}src/main/resources/controllers/preview.ts[]
----

== The test
== Tests

In this test `mock-xp` is used to set up a project repo, a person folder, a couple of images, and a couple content items (of type `person`) which reference the images.
In order for the test file to not become overly large, it's been split it into smaller parts:

In addition, mock-xp's `Log` is used to get nice colorful logging.
=== Mock Portal Library

In order for `libPortal.getContent()` to work, `request` property is set on the `libPortal` object.
.test/server/mockXP.ts
[source, typescript]
----
include::{sourcedir}test/server/mockXP.ts[]
----

=== Mock Thymeleaf library

Finally, the `/lib/thymeleaf` 's `render` mock simply returns the model object, so the actual html rendering is not triggered.
Notice the `/lib/thymeleaf` 's `render` mock simply returns the model object, so the actual html rendering is not triggered.

.test/server/mockLibThymeleaf.ts
[source, typescript]
----
include::{sourcedir}test/server/mockLibThymeleaf.ts[]
----

NOTE: If anyone is able to find or create a test for thymeleaf rendering, please let us know :)

=== The test

In this test `mock-xp` is used to set up a project repo, a person folder, a couple of images, and a couple content items (of type `person`) which reference the images.

In addition, mock-xp's `Log` is used to get nice colorful logging.

In order for `libPortal.getContent()` to work, `request` property is set on the `libPortal` object.

.src/main/resources/controllers/preview.test.ts
[source, typescript]
----
include::{sourcedir}src/main/resources/controllers/preview.test.ts[]
----


== Summary

This guide, showed how to write tests for Enonic XP applications using Jest in combination with Mock XP.
Expand Down
83 changes: 5 additions & 78 deletions src/main/resources/controllers/preview.test.ts
Original file line number Diff line number Diff line change
@@ -1,70 +1,26 @@
//──────────────────────────────────────────────────────────────────────────────
// Type imports
//──────────────────────────────────────────────────────────────────────────────
import type {ByteSource} from '@enonic-types/core';
import type {
assetUrl as assetUrlType,
getContent as getContentType,
imageUrl as imageUrlType,
} from '@enonic-types/lib-portal';
import type {Log, Resolve} from '../../../../test/server/global';


//──────────────────────────────────────────────────────────────────────────────
// Value imports
//──────────────────────────────────────────────────────────────────────────────
import {
describe,
expect,
jest,
test as it
} from '@jest/globals';
import {
App,
LibContent,
LibPortal,
Request,
Server
} from '@enonic/mock-xp';
libContent,
libPortal,
server,
} from '../../../../test/server/mockXP';
import '../../../../test/server/mockLibThymeleaf';
import {readFileSync} from 'fs';
import {
join,
resolve as pathResolve
} from 'path';


//──────────────────────────────────────────────────────────────────────────────
// Constants
//──────────────────────────────────────────────────────────────────────────────
const APP_KEY = 'com.example.tutorial.jest';
const PROJECT_NAME = 'intro';


//──────────────────────────────────────────────────────────────────────────────
// Mock XP
//──────────────────────────────────────────────────────────────────────────────
const server = new Server({
loglevel: 'debug'
}).createProject({
projectName: PROJECT_NAME
}).setContext({
projectName: PROJECT_NAME
});

const app = new App({
key: APP_KEY
});

const libContent = new LibContent({
server
});

const libPortal = new LibPortal({
app,
server
});


//──────────────────────────────────────────────────────────────────────────────
// Mock globals
//──────────────────────────────────────────────────────────────────────────────
Expand All @@ -86,35 +42,6 @@ globalThis.resolve = (path: string): ReturnType<Resolve> => {
}


//──────────────────────────────────────────────────────────────────────────────
// Mock modules
//──────────────────────────────────────────────────────────────────────────────
declare type Model = Record<string, unknown>;
declare type RenderFn = (
_view: string,
_model: Model,
_options: Record<string, unknown>
) => Model;

jest.mock('/lib/thymeleaf', () => ({
render: jest.fn<RenderFn>().mockImplementation((
_view,
model,
// options
) => {
return model; // Not testing the actual rendering, just that the model is correct.
})
}), { virtual: true });

jest.mock('/lib/xp/portal', () => {
return {
assetUrl: jest.fn<typeof assetUrlType>((a) => libPortal.assetUrl(a)),
getContent: jest.fn<typeof getContentType>(() => libPortal.getContent()),
imageUrl: jest.fn<typeof imageUrlType>((a) => libPortal.imageUrl(a)),
}
}, { virtual: true });


//──────────────────────────────────────────────────────────────────────────────
// Test data
//──────────────────────────────────────────────────────────────────────────────
Expand Down
20 changes: 20 additions & 0 deletions test/server/mockLibThymeleaf.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import {jest} from '@jest/globals';


declare type Model = Record<string, unknown>;
declare type RenderFn = (
_view: string,
_model: Model,
_options: Record<string, unknown>
) => Model;


jest.mock('/lib/thymeleaf', () => ({
render: jest.fn<RenderFn>().mockImplementation((
_view,
model,
// options
) => {
return model; // Not testing the actual rendering, just that the model is correct.
})
}), { virtual: true });
54 changes: 54 additions & 0 deletions test/server/mockXP.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import type {
assetUrl as assetUrlType,
getContent as getContentType,
imageUrl as imageUrlType,
} from '@enonic-types/lib-portal';


import {
App,
LibContent,
LibPortal,
Server
} from '@enonic/mock-xp';
import {jest} from '@jest/globals';


export {
Request,
} from '@enonic/mock-xp';


const APP_KEY = 'com.example.tutorial.jest';
const PROJECT_NAME = 'intro';


export const server = new Server({
loglevel: 'debug'
}).createProject({
projectName: PROJECT_NAME
}).setContext({
projectName: PROJECT_NAME
});

const app = new App({
key: APP_KEY
});

export const libContent = new LibContent({
server
});

export const libPortal = new LibPortal({
app,
server
});


jest.mock('/lib/xp/portal', () => {
return {
assetUrl: jest.fn<typeof assetUrlType>((params) => libPortal.assetUrl(params)),
getContent: jest.fn<typeof getContentType>(() => libPortal.getContent()),
imageUrl: jest.fn<typeof imageUrlType>((params) => libPortal.imageUrl(params)),
}
}, { virtual: true });

0 comments on commit 5e1e4ed

Please sign in to comment.