Skip to content

Commit

Permalink
feat: Add tests to sample applications. (#927)
Browse files Browse the repository at this point in the history
* feat: Add tests to sample applications.

* 4.0.0-internal.17

* Put internal publish command to README.md.

* Export ApplicationDefinition type.

* 4.0.0-internal.18

* Add tests for chat sample.

* Add missing validation checks.

* 4.0.0-internal.19

* Add more tests.

* 4.0.0-internal.20

* Add missing tests.

* 4.0.0-internal.21

* Add application tests.
  • Loading branch information
goloroden committed Jun 18, 2020
1 parent 1bbf353 commit e85693e
Show file tree
Hide file tree
Showing 29 changed files with 715 additions and 17 deletions.
102 changes: 102 additions & 0 deletions .dependabot/config.yml
Expand Up @@ -18,6 +18,108 @@ update_configs:
update_type: "all"
version_requirement_updates: "increase_versions"

- package_manager: "javascript"
directory: "/templates/blank/javascript"
update_schedule: "live"
default_assignees:
- "goloroden"
- "yeldiRium"
default_labels:
- "Dependencies"
commit_message:
prefix: "fix"
prefix_development: "chore"
allowed_updates:
- match:
dependency_type: "direct"
update_type: "all"
version_requirement_updates: "increase_versions"

- package_manager: "javascript"
directory: "/templates/blank/typescript"
update_schedule: "live"
default_assignees:
- "goloroden"
- "yeldiRium"
default_labels:
- "Dependencies"
commit_message:
prefix: "fix"
prefix_development: "chore"
allowed_updates:
- match:
dependency_type: "direct"
update_type: "all"
version_requirement_updates: "increase_versions"

- package_manager: "javascript"
directory: "/templates/chat/javascript"
update_schedule: "live"
default_assignees:
- "goloroden"
- "yeldiRium"
default_labels:
- "Dependencies"
commit_message:
prefix: "fix"
prefix_development: "chore"
allowed_updates:
- match:
dependency_type: "direct"
update_type: "all"
version_requirement_updates: "increase_versions"

- package_manager: "javascript"
directory: "/templates/chat/typescript"
update_schedule: "live"
default_assignees:
- "goloroden"
- "yeldiRium"
default_labels:
- "Dependencies"
commit_message:
prefix: "fix"
prefix_development: "chore"
allowed_updates:
- match:
dependency_type: "direct"
update_type: "all"
version_requirement_updates: "increase_versions"

- package_manager: "javascript"
directory: "/templates/chat-simplified/javascript"
update_schedule: "live"
default_assignees:
- "goloroden"
- "yeldiRium"
default_labels:
- "Dependencies"
commit_message:
prefix: "fix"
prefix_development: "chore"
allowed_updates:
- match:
dependency_type: "direct"
update_type: "all"
version_requirement_updates: "increase_versions"

- package_manager: "javascript"
directory: "/templates/chat-simplified/typescript"
update_schedule: "live"
default_assignees:
- "goloroden"
- "yeldiRium"
default_labels:
- "Dependencies"
commit_message:
prefix: "fix"
prefix_development: "chore"
allowed_updates:
- match:
dependency_type: "direct"
update_type: "all"
version_requirement_updates: "increase_versions"

- package_manager: "docker"
directory: "/docker/wolkenkit-mariadb"
update_schedule: "daily"
Expand Down
10 changes: 9 additions & 1 deletion README.md
Expand Up @@ -90,8 +90,16 @@ Ideally you can also include a [short but complete code sample](http://sscce.org

## Running the build

To build this module use [roboter](https://www.npmjs.com/package/roboter).
To build this module use [roboter](https://www.npmjs.com/package/roboter):

```shell
$ npx roboter
```

## Publishing an internal version

While working on wolkenkit itself, it is sometimes necessary to publish an internal version to npm, e.g. to be able to install wolkenkit from the registry. To publish an internal version run the following commands:

```shell
$ npx roboter build && npm version 4.0.0-internal.<id> && npm publish --tag internal && git push --tags
```
12 changes: 8 additions & 4 deletions lib/common/utils/test/sandbox.ts
Expand Up @@ -131,7 +131,7 @@ interface SandboxWithResult<TState extends State> {

then(callback: ((parameters: {
state: State;
domainEvents: DomainEventWithState<DomainEventData, State>[];
domainEvents: DomainEvent<DomainEventData>[];
}) => void | Promise<void>)): Promise<void>;
}

Expand Down Expand Up @@ -382,7 +382,7 @@ const sandboxWithResult = function <TState extends State> (sandboxConfiguration:

async then (callback: ((parameters: {
state: TState;
domainEvents: DomainEventWithState<DomainEventData, TState>[];
domainEvents: DomainEvent<DomainEventData>[];
}) => void | Promise<void>)): Promise<void> {
const lockStore = sandboxConfiguration.lockStore ?? await createLockStore({ type: 'InMemory', options: {}});
const domainEventStore = sandboxConfiguration.domainEventStore ?? await createDomainEventStore({ type: 'InMemory', options: {}});
Expand Down Expand Up @@ -425,12 +425,16 @@ const sandboxWithResult = function <TState extends State> (sandboxConfiguration:
aggregateIdentifier: sandboxConfiguration.aggregateIdentifier
});

let domainEvents: DomainEventWithState<DomainEventData, TState>[] = [];
let domainEventsWithState: DomainEventWithState<DomainEventData, TState>[] = [];

for (const command of sandboxConfiguration.commands) {
domainEvents = await aggregateInstance.handleCommand({ command });
domainEventsWithState = await aggregateInstance.handleCommand({ command });
}

const domainEvents = domainEventsWithState.map(
(domainEventWithState): DomainEvent<DomainEventData> => domainEventWithState.withoutState()
);

// eslint-disable-next-line callback-return
await callback({ domainEvents, state: aggregateInstance.state });
}
Expand Down
2 changes: 2 additions & 0 deletions lib/wolkenkit.ts
@@ -1,6 +1,7 @@
import { Aggregate } from './common/elements/Aggregate';
import { AggregateService } from './common/services/AggregateService';
import { AggregatesService } from './common/services/AggregatesService';
import { ApplicationDefinition } from './common/application/ApplicationDefinition';
import { ClientService } from './common/services/ClientService';
import { Command } from './common/elements/Command';
import { CommandData } from './common/elements/CommandData';
Expand Down Expand Up @@ -29,6 +30,7 @@ export {
Aggregate,
AggregateService,
AggregatesService,
ApplicationDefinition,
ClientService,
Command,
CommandData,
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
@@ -1,6 +1,6 @@
{
"name": "wolkenkit",
"version": "4.0.0-ctp.1",
"version": "4.0.0-internal.21",
"description": "wolkenkit is an open-source CQRS and event-sourcing framework based on Node.js, and it supports JavaScript and TypeScript.",
"contributors": [
{
Expand Down
12 changes: 11 additions & 1 deletion templates/blank/javascript/package.json
Expand Up @@ -3,5 +3,15 @@
"version": "0.0.1",
"description": "",
"dependencies": {},
"devDependencies": {}
"devDependencies": {
"assertthat": "5.1.1",
"mocha": "8.0.1",
"run-script-os": "1.1.1",
"uuidv4": "6.1.0"
},
"scripts": {
"test": "run-script-os",
"test:win32": "npx wolkenkit build && npx mocha --async-only --bail --recursive --ui tdd '.\\test\\**\\*.js'",
"test:default": "npx wolkenkit build && npx mocha --async-only --bail --recursive --ui tdd './test/**/*.js'"
}
}
@@ -0,0 +1,34 @@
'use strict';

const { assert } = require('assertthat');
const path = require('path');
const { uuid } = require('uuidv4');
const { getApplicationDefinition, sandbox } = require('wolkenkit');

suite('sampleAggregate', () => {
let applicationDefinition;

suiteSetup(async () => {
applicationDefinition = await getApplicationDefinition({
applicationDirectory: path.join(__dirname, '..', '..', '..')
});
});

suite('sampleCommand', () => {
test('publishes a sample domain event.', async () => {
const contextIdentifier = { name: 'sampleContext' };
const aggregateIdentifier = { name: 'sampleAggregate', id: uuid() };

await sandbox().
withApplicationDefinition({ applicationDefinition }).
forAggregate({ contextIdentifier, aggregateIdentifier }).
when({ name: 'sampleCommand', data: {}}).
then(({ domainEvents, state }) => {
assert.that(domainEvents.length).is.equalTo(1);
assert.that(domainEvents[0].name).is.equalTo('sampleDomainEvent');
assert.that(domainEvents[0].data).is.equalTo({});
assert.that(state).is.equalTo({ domainEventNames: [ 'sampleDomainEvent' ]});
});
});
});
});
14 changes: 13 additions & 1 deletion templates/blank/typescript/package.json
Expand Up @@ -3,5 +3,17 @@
"version": "0.0.1",
"description": "",
"dependencies": {},
"devDependencies": {}
"devDependencies": {
"@types/mocha": "7.0.2",
"assertthat": "5.1.1",
"mocha": "8.0.1",
"run-script-os": "1.1.1",
"ts-node": "8.10.2",
"uuidv4": "6.1.0"
},
"scripts": {
"test": "run-script-os",
"test:win32": "npx wolkenkit build && npx mocha --async-only --bail --require ts-node/register --recursive --ui tdd '.\\test\\**\\*.ts'",
"test:default": "npx wolkenkit build && npx mocha --async-only --bail --require ts-node/register --recursive --ui tdd './test/**/*.ts'"
}
}
@@ -0,0 +1,33 @@
import { assert } from 'assertthat';
import path from 'path';
import { SampleCommandData } from '../../../server/domain/sampleContext/sampleAggregate/commands/sampleCommand';
import { uuid } from 'uuidv4';
import { ApplicationDefinition, getApplicationDefinition, sandbox } from 'wolkenkit';

suite('sampleAggregate', (): void => {
let applicationDefinition: ApplicationDefinition;

suiteSetup(async (): Promise<void> => {
applicationDefinition = await getApplicationDefinition({
applicationDirectory: path.join(__dirname, '..', '..', '..')
});
});

suite('sampleCommand', (): void => {
test('publishes a sample domain event.', async (): Promise<void> => {
const contextIdentifier = { name: 'sampleContext' };
const aggregateIdentifier = { name: 'sampleAggregate', id: uuid() };

await sandbox().
withApplicationDefinition({ applicationDefinition }).
forAggregate({ contextIdentifier, aggregateIdentifier }).
when<SampleCommandData>({ name: 'sampleCommand', data: {}}).
then(({ domainEvents, state }): void => {
assert.that(domainEvents.length).is.equalTo(1);
assert.that(domainEvents[0].name).is.equalTo('sampleDomainEvent');
assert.that(domainEvents[0].data).is.equalTo({});
assert.that(state).is.equalTo({ domainEventNames: [ 'sampleDomainEvent' ]});
});
});
});
});
1 change: 1 addition & 0 deletions templates/blank/typescript/tsconfig.json
@@ -1,5 +1,6 @@
{
"compilerOptions": {
"esModuleInterop": true,
"rootDir": ".",
"sourceMap": true
},
Expand Down
12 changes: 11 additions & 1 deletion templates/chat-simplified/javascript/package.json
Expand Up @@ -3,5 +3,15 @@
"version": "0.0.1",
"description": "",
"dependencies": {},
"devDependencies": {}
"devDependencies": {
"assertthat": "5.1.1",
"mocha": "8.0.1",
"run-script-os": "1.1.1",
"uuidv4": "6.1.0"
},
"scripts": {
"test": "run-script-os",
"test:win32": "npx wolkenkit build && npx mocha --async-only --bail --recursive --ui tdd '.\\test\\**\\*.js'",
"test:default": "npx wolkenkit build && npx mocha --async-only --bail --recursive --ui tdd './test/**/*.js'"
}
}
Expand Up @@ -29,6 +29,9 @@ const message = {
if (!command.data.text) {
throw new error.CommandRejected('Text is missing.');
}
if (!aggregate.isPristine()) {
throw new error.CommandRejected('Message was already sent.');
}

aggregate.publishDomainEvent('sent', {
text: command.data.text
Expand All @@ -50,7 +53,11 @@ const message = {
return true;
},

handle (state, _command, { aggregate }) {
handle (state, _command, { aggregate, error }) {
if (aggregate.isPristine()) {
throw new error.CommandRejected('Message was not yet sent.');
}

aggregate.publishDomainEvent('liked', {
likes: state.likes + 1
});
Expand Down

0 comments on commit e85693e

Please sign in to comment.