Skip to content

Commit

Permalink
refactor(backend): add abstraction
Browse files Browse the repository at this point in the history
Add abstraction to handle mocking in tests.
  • Loading branch information
MaciejSikorski authored and Sikora00 committed Oct 3, 2020
1 parent ed0f8ba commit 5244ed4
Show file tree
Hide file tree
Showing 135 changed files with 1,830 additions and 559 deletions.
8 changes: 4 additions & 4 deletions .env-sample
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ ICES_CONTAINER_NAME=slack_dj_ices
LOCAL_USER_ID=1000

DB_HOST=database
MYSQL_DATABASE=slack_dj
MYSQL_PASSWORD=sdj123123
MYSQL_ROOT_PASSWORD=rootPass123
MYSQL_USER=sdj
DB_DATABASE=slack_dj
DB_PASSWORD=sdj123123
DB_ROOT_PASSWORD=rootPass123
DB_USERNAME=sdj

NG_CONTAINER_NAME=slack_dj_ng
NG_EXTERNAL_STREAM=stream.open.fm/109
Expand Down
17 changes: 9 additions & 8 deletions .github/workflows/base.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,19 +81,20 @@ jobs:
parallel-finished: true

e2e:
runs-on: ubuntu-16.04
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: Build the stack
run: docker-compose -f docker-compose-e2e.yml up -d
- name: npm install
run: npm ci
run: docker exec sdj-e2e-backend bash -c "npm ci"
- name: affected:e2e
run: npm run affected:e2e -- --base origin/develop
run: docker exec sdj-e2e-backend bash -c "npm run affected:e2e -- --parallel --all"
env:
CI: true
DB_ROOT_PASSWORD: ${{ secrets.DB_PASSWORD }}
DB_HOST: ${{ secrets.DB_HOST }}
DB_USERNAME: root
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}

lint:
runs-on: ubuntu-latest
Expand Down
12 changes: 6 additions & 6 deletions .github/workflows/task.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,20 @@ jobs:
CI: true

e2e:
runs-on: ubuntu-16.04
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Build the stack
run: docker-compose -f docker-compose-e2e.yml up -d
- name: npm install
run: docker exec sdj-e2e-backend bash -c "npm ci"
- name: affected:e2e
run: docker exec sdj-e2e-backend bash -c "npm run affected:e2e -- --base origin/develop"
run: docker exec sdj-e2e-backend bash -c "npm run affected:e2e -- --parallel --base origin/develop"
env:
MYSQL_ROOT_PASSWORD: ${{ secrets.MYSQL_ROOT_PASSWORD }}
MYSQL_DATABASE: ${{ secrets.MYSQL_DATABASE }}
MYSQL_USER: ${{ secrets.MYSQL_USER }}
MYSQL_PASSWORD: ${{ secrets.MYSQL_PASSWORD }}
DB_ROOT_PASSWORD: ${{ secrets.DB_PASSWORD }}
DB_HOST: ${{ secrets.DB_HOST }}
DB_USERNAME: root
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}

lint:
runs-on: ubuntu-latest
Expand Down
115 changes: 85 additions & 30 deletions angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -538,34 +538,6 @@
}
}
},
"backend-shared-util-mp3": {
"root": "libs/backend/shared/util-mp3",
"sourceRoot": "libs/backend/shared/util-mp3/src",
"projectType": "library",
"schematics": {},
"architect": {
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"libs/backend/shared/util-mp3/tsconfig.lib.json",
"libs/backend/shared/util-mp3/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**",
"!libs/backend/shared/util-mp3/**/*"
]
}
},
"test": {
"builder": "@nrwl/jest:jest",
"options": {
"jestConfig": "libs/backend/shared/util-mp3/jest.config.js",
"passWithNoTests": true
}
}
}
},
"backend-radio-ui-redis": {
"projectType": "library",
"root": "libs/backend/radio/ui-redis",
Expand Down Expand Up @@ -1453,8 +1425,7 @@
"builder": "@nrwl/jest:jest",
"options": {
"jestConfig": "apps/backend-e2e/jest.config.js",
"passWithNoTests": true,
"runInBand": true
"passWithNoTests": true
}
}
}
Expand All @@ -1474,6 +1445,90 @@
}
}
}
},
"backend-radio-infrastructure-youtube-api": {
"root": "libs/backend/radio/infrastructure-youtube-api",
"sourceRoot": "libs/backend/radio/infrastructure-youtube-api/src",
"projectType": "library",
"schematics": {},
"architect": {
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"libs/backend/radio/infrastructure-youtube-api/tsconfig.lib.json",
"libs/backend/radio/infrastructure-youtube-api/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**",
"!libs/backend/radio/infrastructure-youtube-api/**/*"
]
}
},
"test": {
"builder": "@nrwl/jest:jest",
"options": {
"jestConfig": "libs/backend/radio/infrastructure-youtube-api/jest.config.js",
"passWithNoTests": true
}
}
}
},
"backend-radio-infrastructure-mp3-gain": {
"root": "libs/backend/radio/infrastructure-mp3-gain",
"sourceRoot": "libs/backend/radio/infrastructure-mp3-gain/src",
"projectType": "library",
"schematics": {},
"architect": {
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"libs/backend/radio/infrastructure-mp3-gain/tsconfig.lib.json",
"libs/backend/radio/infrastructure-mp3-gain/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**",
"!libs/backend/radio/infrastructure-mp3-gain/**/*"
]
}
},
"test": {
"builder": "@nrwl/jest:jest",
"options": {
"jestConfig": "libs/backend/radio/infrastructure-mp3-gain/jest.config.js",
"passWithNoTests": true
}
}
}
},
"backend-radio-infrastructure-typeorm": {
"root": "libs/backend/radio/infrastructure-typeorm",
"sourceRoot": "libs/backend/radio/infrastructure-typeorm/src",
"projectType": "library",
"schematics": {},
"architect": {
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"libs/backend/radio/infrastructure-typeorm/tsconfig.lib.json",
"libs/backend/radio/infrastructure-typeorm/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**",
"!libs/backend/radio/infrastructure-typeorm/**/*"
]
}
},
"test": {
"builder": "@nrwl/jest:jest",
"options": {
"jestConfig": "libs/backend/radio/infrastructure-typeorm/jest.config.js",
"passWithNoTests": true
}
}
}
}
},
"cli": {
Expand Down
12 changes: 6 additions & 6 deletions apps/backend-e2e/src/fixtures/get-next-song.sql
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
INSERT INTO sdj_test.channel (defaultStreamUrl, id, isRunning, name, usersOnline) VALUES (null, '12345', 0, null, 1);
INSERT INTO sdj_test.user (displayName, id, name, realName) VALUES ('Maciek', 'U9SNE3S31', 'mikon0096', 'Maciej Sikorski');
INSERT INTO sdj_test.track (createdAt, duration, id, skips, title, addedById) VALUES ('2019-05-21 08:58:28', 210, '_4VCpTZye10', 0, 'Three Days Grace - Break (Official Music Video)', 'U9SNE3S31');
INSERT INTO sdj_test.track (createdAt, duration, id, skips, title, addedById) VALUES ('2019-10-01 20:46:16', 175, '_D1rrdFcj1U', 0, 'Matoma & Enrique Iglesias – I Don''t Dance (Without You) [feat. Konshens] [Official Lyric Video]', 'U9SNE3S31');
INSERT INTO sdj_test.queued_track (createdAt, id, `order`, playedAt, randomized, addedById, trackId, playedInId) VALUES ('2019-05-19 20:56:59', 2, 0, null, 0, 'U9SNE3S31', '_4VCpTZye10', '12345');
INSERT INTO sdj_test.queued_track (createdAt, id, `order`, playedAt, randomized, addedById, trackId, playedInId) VALUES ('2019-05-19 21:02:36', 4, 0, null, 0, 'U9SNE3S31', '_D1rrdFcj1U', '12345');
INSERT INTO channel (defaultStreamUrl, id, isRunning, name, usersOnline) VALUES (null, '12345', 0, null, 1);
INSERT INTO user (displayName, id, name, realName) VALUES ('Maciek', 'U9SNE3S31', 'mikon0096', 'Maciej Sikorski');
INSERT INTO track (createdAt, duration, id, skips, title, addedById) VALUES ('2019-05-21 08:58:28', 210, '_4VCpTZye10', 0, 'Three Days Grace - Break (Official Music Video)', 'U9SNE3S31');
INSERT INTO track (createdAt, duration, id, skips, title, addedById) VALUES ('2019-10-01 20:46:16', 175, '_D1rrdFcj1U', 0, 'Matoma & Enrique Iglesias – I Don''t Dance (Without You) [feat. Konshens] [Official Lyric Video]', 'U9SNE3S31');
INSERT INTO queued_track (createdAt, id, `order`, playedAt, randomized, addedById, trackId, playedInId) VALUES ('2019-05-19 20:56:59', 2, 0, null, 0, 'U9SNE3S31', '_4VCpTZye10', '12345');
INSERT INTO queued_track (createdAt, id, `order`, playedAt, randomized, addedById, trackId, playedInId) VALUES ('2019-05-19 21:02:36', 4, 0, null, 0, 'U9SNE3S31', '_D1rrdFcj1U', '12345');
84 changes: 84 additions & 0 deletions apps/backend-e2e/src/integration/add-track-to-queue.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { INestApplication } from '@nestjs/common';
import { Test } from '@nestjs/testing';
import {
TrackDataService,
TrackService,
} from '@sdj/backend/radio/core/application-services';
import {
Channel,
QueuedTrack,
Track,
User,
} from '@sdj/backend/radio/core/domain';
import { SlackModule } from '@sdj/backend/radio/ui-slack';
import { WebSocketModule } from '@sdj/backend/radio/ui-web-socket';
import { BackendSharedTestingKernelModule } from '@sdj/backend/shared/kernel';
import { SlackService, SlackTestingService } from '@sikora00/nestjs-slack-bot';
import 'jest-marbles';
import { getRepository } from 'typeorm';
import { UserDataService } from '../../../../libs/backend/radio/ui-slack/src/lib/bot/lib/interceptors/user-data.service';
import { createDb } from '../utils/create-db';

describe('Add Track To Queue', () => {
let app: INestApplication;
let slack: jest.Mocked<SlackTestingService>;
let trackDataService: jest.Mocked<TrackDataService>;
let trackService: jest.Mocked<TrackService>;
let userDataService: jest.Mocked<UserDataService>;

beforeAll(async () => {
process.env.DB_DATABASE = 'sdj_test_add_track_to_queue';
jest.setTimeout(30 * 1000);
await createDb();

const module = await Test.createTestingModule({
imports: [WebSocketModule, SlackModule, BackendSharedTestingKernelModule],
})
.overrideProvider(UserDataService)
.useValue({ getUserData: jest.fn() })
.overrideProvider(TrackDataService)
.useValue({ loadTrackData: jest.fn() })
.overrideProvider(TrackService)
.useValue({ download: jest.fn(), getDuration: jest.fn() })
.compile();
app = module.createNestApplication();
slack = module.get(SlackService);
trackDataService = module.get(TrackDataService);
trackService = module.get(TrackService);
userDataService = module.get(UserDataService);
await app.init();
});

test('saves track, channel, user and queued track in database', (done) => {
userDataService.getUserData.mockResolvedValue({
user: '1234',
name: 'Maciej',
profile: { display_name: 'Maciek', real_name: 'Maciej Sikorski' },
});
slack.fakeReceiveMessage('message', {
type: 'message',
channel: 'abc',
user: '1234',
text: 'play <https://www.youtube.com/watch?v=G8dsvclf3Tk>',
} as any);
trackDataService.loadTrackData.mockResolvedValue({
title: 'Title',
duration: 4 * 60 * 1000,
});
trackService.download.mockResolvedValue('some-path.mp3');
trackService.getDuration.mockResolvedValue(4 * 60 * 1000);
setTimeout(async () => {
expect(await getRepository(User).findOneOrFail('1234')).toBeTruthy();
expect(await getRepository(Channel).findOneOrFail('abc')).toBeTruthy();
expect(await getRepository(QueuedTrack).findOneOrFail(1)).toBeTruthy();
expect(
await getRepository(Track).findOneOrFail('G8dsvclf3Tk')
).toBeTruthy();
done();
}, 5 * 1000);
});

afterAll(async () => {
await app.close();
});
});
16 changes: 5 additions & 11 deletions apps/backend-e2e/src/integration/play-radio-queue.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ import { INestApplication } from '@nestjs/common';
import { Test } from '@nestjs/testing';
import { QueuedTrack } from '@sdj/backend/radio/core/domain';
import { BackendRadioUiRedisModule } from '@sdj/backend/radio/ui-redis';
import { BackendRadioUiRestModule } from '@sdj/backend/radio/ui-rest';
import { SlackModule } from '@sdj/backend/radio/ui-slack';
import { WebSocketModule } from '@sdj/backend/radio/ui-web-socket';
import { connectionConfig } from '@sdj/backend/shared/domain';
import { BackendSharedTestingKernelModule } from '@sdj/backend/shared/kernel';
Expand All @@ -20,15 +18,14 @@ describe('Play Radio Queue', () => {
let app: INestApplication;

beforeAll(async () => {
process.env.DB_DATABASE = 'sdj_test_play_radio_queue';
jest.setTimeout(30 * 1000);
await createDb();

const module = await Test.createTestingModule({
imports: [
BackendRadioUiRestModule,
WebSocketModule,
BackendRadioUiRedisModule,
SlackModule,
BackendSharedTestingKernelModule,
],
}).compile();
Expand Down Expand Up @@ -60,12 +57,10 @@ describe('Play Radio Queue', () => {
});

test('returns 10-sec-of-silence', (done) => {
new Promise((resolve) => {
redisSub.on('message', (channel, message) => {
expect(channel).toEqual(channelId);
expect(message).toEqual('10-sec-of-silence');
done();
});
redisSub.on('message', (channel, message) => {
expect(channel).toEqual(channelId);
expect(message).toEqual('10-sec-of-silence');
done();
});
redisPub.publish('getNext', channelId);
});
Expand Down Expand Up @@ -119,7 +114,6 @@ describe('Play Radio Queue', () => {
expect(channel).toEqual(channelId);
expect(message).toEqual('_4VCpTZye10');
setTimeout(async () => {
// ToDo Make sure that track data are saved before events are emitted
expect(
(await getRepository(QueuedTrack).findOneOrFail(2)).playedAt
).toBeTruthy();
Expand Down
12 changes: 6 additions & 6 deletions apps/backend-e2e/src/utils/create-db.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { createConnection } from 'typeorm';
import { connectionConfig } from '../../../../libs/backend/shared/domain/src';

export async function createDb(): Promise<void> {
const dbName = connectionConfig.db.database;
const dbName = process.env.DB_DATABASE;

const connection = await createConnection({
name: 'create-db',
type: 'mariadb' as 'mariadb',
host: connectionConfig.db.host,
port: connectionConfig.db.port,
username: connectionConfig.db.username,
password: connectionConfig.db.password,
host: process.env.DB_HOST,
port: 3306,
username: process.env.DB_USERNAME,
password: process.env.DB_ROOT_PASSWORD,
});
await connection.query(`DROP DATABASE IF EXISTS ${dbName};`);
await connection.query(`CREATE DATABASE ${dbName}`);
Expand Down
2 changes: 1 addition & 1 deletion apps/backend-e2e/src/utils/ws-client.helper.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import io from 'socket.io-client';
import { INestApplication } from '@nestjs/common';
import io from 'socket.io-client';

export const getClientWebsocketForAppAndNamespace = (
app: INestApplication,
Expand Down
2 changes: 1 addition & 1 deletion apps/ng/src/app/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { NgModule } from '@angular/core';
import { NgSharedKernelModule } from '@sdj/ng/shared/kernel';
import { NgMainShellModule } from '@sdj/ng/main/shell';
import { NgSharedKernelModule } from '@sdj/ng/shared/kernel';
import { AppComponent } from './app.component';

@NgModule({
Expand Down
Loading

0 comments on commit 5244ed4

Please sign in to comment.