Skip to content

Commit 8f9e714

Browse files
authored
Improve coverage of CDCT for optional attributes (#386)
* Remove unnecessary timestamp attribute * Cover optional schema attribute in CDC-Tests It is covered in interactions between Notification & Pipeline and UI & Pipeline The skipped interactions between UI & Pipeline are not adjusted, this will be done in a future commit * Fix lint error * Remove unused return value when updating and deleting pipelines * Fix lint error * Cover health status enum values in CDC-Tests * Let CDCT script remove previously existing containers This change should reduce the flakiness of the provider-side CDC-Tests of the pipeline service. Old entries in the database and old messages in the message queue are avoided that way. * Remove unnecessary timestamp attribute in provider-side CDC-Test * Cover schema attribute for previously skipped interactions * Improve script so it determines the project folder name * Remove unnecessary methods for state handling
1 parent 56a1a30 commit 8f9e714

11 files changed

+396
-193
lines changed

notification/src/pipeline.consumer.pact.test.ts

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,17 @@ if (fs.existsSync(contractPath)) {
2626
fs.unlinkSync(contractPath);
2727
}
2828

29-
const examplePipelineSuccessEvent: PipelineSuccessEvent = {
29+
const examplePipelineSuccessEventWithoutSchema: PipelineSuccessEvent = {
3030
pipelineId: 1,
3131
pipelineName: 'some pipeline name',
3232
data: {},
3333
};
3434

35+
const examplePipelineSuccessEventWithSchema: PipelineSuccessEvent = {
36+
...examplePipelineSuccessEventWithoutSchema,
37+
schema: {},
38+
};
39+
3540
jest.mock('./env', () => ({}));
3641

3742
jest.mock('./notification-config/postgresNotificationRepository', () => {
@@ -52,16 +57,28 @@ const mockNotificationExecutor =
5257

5358
messagePactWith(options, (messagePact) => {
5459
describe('receiving an amqp message', () => {
55-
it('handles a success event', async () => {
56-
const triggerEventHandler = new TriggerEventHandler(
57-
mockPostgresNotificationRepository(),
58-
mockNotificationExecutor(),
59-
);
60+
const triggerEventHandler = new TriggerEventHandler(
61+
mockPostgresNotificationRepository(),
62+
mockNotificationExecutor(),
63+
);
64+
65+
it('handles a success event without schema', async () => {
66+
await messagePact
67+
.given('any state')
68+
.expectsToReceive('a success event without schema')
69+
.withContent(Matchers.like(examplePipelineSuccessEventWithoutSchema))
70+
.verify(
71+
asynchronousBodyHandler(
72+
async (body) => await triggerEventHandler.handleEvent(body),
73+
),
74+
);
75+
});
6076

77+
it('handles a success event with schema', async () => {
6178
await messagePact
6279
.given('any state')
63-
.expectsToReceive('a success event')
64-
.withContent(Matchers.like(examplePipelineSuccessEvent))
80+
.expectsToReceive('a success event with schema')
81+
.withContent(Matchers.like(examplePipelineSuccessEventWithSchema))
6582
.verify(
6683
asynchronousBodyHandler(
6784
async (body) => await triggerEventHandler.handleEvent(body),

pipeline/cdct-provider.sh

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,14 @@ set -e
55

66
dir=$(dirname "$0")
77
cd ${dir}/..
8+
9+
# remove containers that already exist which may distort the initial state of the service
10+
containersToRemove=( "rabbitmq" "pipeline-db" )
11+
for containerName in ${containersToRemove[@]}
12+
do
13+
containerIds=$(docker ps -a -q --filter name=$(basename $PWD)_$containerName)
14+
[[ -n $containerIds ]] && docker rm -f -v $containerIds
15+
done
16+
817
docker-compose -f docker-compose.yml -f docker-compose.provider.yml build pipeline pipeline-db pipeline-outboxer rabbitmq
9-
docker-compose -f docker-compose.yml -f docker-compose.provider.yml up --exit-code-from pipeline pipeline pipeline-db pipeline-outboxer rabbitmq
18+
docker-compose -f docker-compose.yml -f docker-compose.provider.yml up --exit-code-from pipeline pipeline pipeline-db pipeline-outboxer rabbitmq

pipeline/src/amqp.provider.pact.test.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,18 +67,28 @@ describe('Pact Provider Verification', () => {
6767
'any state': async (): Promise<void> => Promise.resolve(),
6868
},
6969
messageProviders: {
70-
'a success event': provideSuccessEvent,
70+
'a success event': provideSuccessEventWithoutSchema,
71+
'a success event without schema': provideSuccessEventWithoutSchema,
72+
'a success event with schema': provideSuccessEventWithSchema,
7173
},
7274
};
7375

74-
async function provideSuccessEvent(): Promise<unknown> {
76+
async function provideSuccessEventWithoutSchema(): Promise<unknown> {
77+
return await provideSuccessEvent(false);
78+
}
79+
80+
async function provideSuccessEventWithSchema(): Promise<unknown> {
81+
return await provideSuccessEvent(true);
82+
}
83+
84+
async function provideSuccessEvent(withSchema: boolean): Promise<unknown> {
7585
await pgClient.transaction(async (client) => {
7686
await EventPublisher.publishSuccess(
7787
client,
7888
1,
7989
'some pipeline name',
8090
{},
81-
{ some: 'schema' },
91+
withSchema ? {} : undefined,
8292
);
8393
});
8494
return await waitForMessage(successMessages);

pipeline/src/api/rest/pipelineTransformedDataEndpoint.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export class PipelineTranformedDataEndpoint {
3939
const transformedDataMetaData: PipelineTransformedDataMetaData = {
4040
id: transformedData.id,
4141
healthStatus: transformedData.healthStatus,
42-
timestamp: transformedData.createdAt as string,
42+
timestamp: transformedData.createdAt,
4343
};
4444
res.status(200).json(transformedDataMetaData);
4545
};

pipeline/src/pipeline-config/model/pipelineTransformedData.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export interface PipelineTransformedData {
1414
export interface PipelineTransformedDataMetaData {
1515
id: number;
1616
healthStatus: string;
17-
timestamp: string;
17+
timestamp?: string;
1818
}
1919

2020
export type PipelineTransformedDataDTO = Omit<

pipeline/src/ui.provider.pact.test.ts

Lines changed: 45 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -113,12 +113,30 @@ describe('Pact Provider Verification', () => {
113113
stateHandlers: {
114114
'any state': setupEmptyState,
115115
'no pipelines exist': setupEmptyState,
116-
'some pipelines exist': setupSomePipelineConfigs,
117-
'pipeline with id 1 exists': setupSomePipelineConfigs,
116+
'some pipelines without schemas exist':
117+
setupSomePipelineConfigsWithoutSchemas,
118+
'some pipelines with schemas exist':
119+
setupSomePipelineConfigsWithSchemas,
120+
'pipeline with id 1 exists': setupSomePipelineConfigsWithoutSchemas,
121+
'pipeline with id 1 exists and has no schema':
122+
setupSomePipelineConfigsWithoutSchemas,
123+
'pipeline with id 1 exists and has a schema':
124+
setupSomePipelineConfigsWithSchemas,
118125
'pipeline with id 1 does not exist': setupEmptyState,
119-
'pipelines with datasource id 2 exist': setupSomePipelineConfigs,
126+
'pipelines with datasource id 2 exist and have schemas':
127+
setupSomePipelineConfigsWithSchemas,
128+
'pipelines with datasource id 2 exist and have no schemas':
129+
setupSomePipelineConfigsWithoutSchemas,
120130
'pipelines with datasource id 2 do not exist': setupEmptyState,
121-
'transformed data with id 1 exists': setupSomePipelineTransformedData,
131+
'transformed data with id 1 and health status OK exists':
132+
async (): Promise<void> =>
133+
setupSomePipelineTransformedData(HealthStatus.OK),
134+
'transformed data with id 1 and health status WARNING exists':
135+
async (): Promise<void> =>
136+
setupSomePipelineTransformedData(HealthStatus.WARNING),
137+
'transformed data with id 1 and health status FAILED exists':
138+
async (): Promise<void> =>
139+
setupSomePipelineTransformedData(HealthStatus.FAILED),
122140
'transformed data with id 1 does not exist': setupEmptyState,
123141
},
124142
});
@@ -134,20 +152,29 @@ async function setupEmptyState(): Promise<void> {
134152
return Promise.resolve();
135153
}
136154

137-
async function setupSomePipelineConfigs(): Promise<void> {
155+
async function setupSomePipelineConfigsWithoutSchemas(): Promise<void> {
156+
await setupSomePipelineConfigs(false);
157+
}
158+
159+
async function setupSomePipelineConfigsWithSchemas(): Promise<void> {
160+
await setupSomePipelineConfigs(true);
161+
}
162+
163+
async function setupSomePipelineConfigs(withSchemas: boolean): Promise<void> {
138164
clearState();
139-
addSamplePipelineConfig(++nextPipelineConfigId, 2, true);
140-
addSamplePipelineConfig(++nextPipelineConfigId, 3, false);
141-
addSamplePipelineConfig(++nextPipelineConfigId, 2, false);
165+
addSamplePipelineConfig(2, withSchemas);
166+
addSamplePipelineConfig(3, withSchemas);
167+
addSamplePipelineConfig(2, withSchemas);
142168

143169
return Promise.resolve();
144170
}
145171

146-
async function setupSomePipelineTransformedData(): Promise<void> {
172+
async function setupSomePipelineTransformedData(
173+
healthStatus: HealthStatus,
174+
): Promise<void> {
147175
clearState();
148-
addSamplePipelineTransformedData(1);
149-
addSamplePipelineTransformedData(2);
150-
addSamplePipelineTransformedData(3);
176+
addSamplePipelineTransformedData(1, healthStatus);
177+
addSamplePipelineTransformedData(2, healthStatus);
151178

152179
return Promise.resolve();
153180
}
@@ -164,12 +191,11 @@ function clearPipelineConfigs(): void {
164191
}
165192

166193
function addSamplePipelineConfig(
167-
id: number,
168194
datasourceId: number,
169195
withSchema: boolean,
170196
): void {
171197
const pipelineConfig: PipelineConfig = {
172-
id: id,
198+
id: ++nextPipelineConfigId,
173199
datasourceId: datasourceId,
174200
metadata: {
175201
author: 'some author',
@@ -192,16 +218,15 @@ function clearPipelineTransformedData(): void {
192218
pipelineTransformedData.splice(0, pipelineTransformedData.length);
193219
}
194220

195-
function addSamplePipelineTransformedData(id: number): void {
221+
function addSamplePipelineTransformedData(
222+
id: number,
223+
healthStatus: HealthStatus,
224+
): void {
196225
const data: PipelineTransformedData = {
197226
id: id,
198227
pipelineId: 42,
199-
healthStatus: HealthStatus.OK,
228+
healthStatus: healthStatus,
200229
data: {},
201-
202-
/* TODO without this 'createdAt' field, the UI would not be able to fully interpret the response
203-
because it expects the 'timestamp' field to be present which is derived from 'createdAt' */
204-
createdAt: 'some creation date',
205230
};
206231
pipelineTransformedData.push(data);
207232
}

0 commit comments

Comments
 (0)