Bingo for meetings–finalizing API for web–part 16
Bingo
Bingo is a small project, written in TypeScript , and developed with Alexandru Badita in launch break (one hour - more or less). You can find sources at https://github.com/alexandru360/PresentationBingoCards/ . Those are my blog posts for Bingo : ( scroll below for the post)The API that we want to create is
- create meeting
- add participant
- check cards
- see result meeting(
Those API’s were simpler for the console application, because of the single participant involved.
There are also some technical problems and some architectural ones.
Let’s start with technical: nestjs suggest ( as per sample project with contacts) to add a route like:
@Put(':id/addParticipant') async addParticipant(@Param('id') id: any, @Body() nameParticipant: string): Promise<Meeting> { // console.log(`userName : ${JSON.stringify(cm.userName)} meetingName: ${JSON.stringify(cm.meetingName)}`); return this.meetingsService.AddParticipant(id, nameParticipant); }
However , this is not available to be tested via Swagger – so we modify to
export class AddParticipant { @ApiModelProperty() meetingId: any; @ApiModelProperty() nameParticipant: string; } //CODE OF THE CONTROLLER OMITTED @Put('addParticipant') async addParticipant(@Body() addParticipant: AddParticipant): Promise<Meeting> { // console.log(`userName : ${JSON.stringify(cm.userName)} meetingName: ${JSON.stringify(cm.meetingName)}`); return this.meetingsService.AddParticipant(addParticipant.meetingId, addParticipant.nameParticipant); }
Also, when we handle in the meeting service the CheckCard we discover to be missing something for the original DDD model . For example, we need a FindCard and FindParticipantAfterName .
public checkCard(idMeeting: any, idCard: number, nameParticipant:string ): Meeting{ const m = this.meetings.find(it => it.Id === idMeeting ); // TODO: throw if meeting is null const c = m.FindCard(idCard); // TODO: throw if card is null const p = m.FindParticipantAfterName(nameParticipant); // TODO: throw if participant is null m.CheckCardByParticipant(c, p); return m; }
For the architectural ones:
- The service that we just created should be tested and put into the right project. It could belong to the bingo-meeting-objects.
- The controller has some classes that should be tested. However, the classes involving in the @Body have swagger attributes, so they cannot be moved into bingo-meeting-objects .
export class AddParticipant { //bingo-meeting-objects should not have reference to swagger properties @ApiModelProperty() meetingId: any; @ApiModelProperty() nameParticipant: string; }
Download the actual code from https://github.com/alexandru360/PresentationBingoCards/releases/tag/api_final
Bingo for meetings-nestjs–create meeting api -part 15
Bingo
Bingo is a small project, written in TypeScript , and developed with Alexandru Badita in launch break (one hour - more or less). You can find sources at https://github.com/alexandru360/PresentationBingoCards/ . Those are my blog posts for Bingo : ( scroll below for the post)So now it is time to expose our objects as HTTP API. We have decided to go with nest.js because has support for TypeScript. The documentation to install is pretty obvious at https://docs.nestjs.com/ .
Now we must code the endpoint to create a meeting. As per the nest.js documentation , we should create a module ,a controller and a service to redirect calls . The problem is that , to create a meeting, we should transmit 2 parameters: userName and meetingName. To do this via HTTP, we must create a new class with this 2 parameters :
export class CreateMeeting { readonly userName: string; readonly meetingName: string; }
Also we want to add Swagger as show at https://docs.nestjs.com/recipes/swagger . And for this, according to the documentation , we should decorate the class:
import { ApiModelProperty } from '@nestjs/swagger'; export class CreateMeeting { @ApiModelProperty() readonly userName: string; @ApiModelProperty() readonly meetingName: string; }
And now we have a controller with 2 functions – get – to show all meetings – and post- to create the meeting:
@Controller('meetings') export class MeetingsController { constructor(private meetingsService: MeetingService){} @Get() index(): Meeting[] { return this.meetingsService.meetings; } @Post() async create(@Body() cm: CreateMeeting): Promise<Meeting> { console.log(`userName : ${JSON.stringify(cm.userName)} meetingName: ${JSON.stringify(cm.meetingName)}`); return this.meetingsService.create(cm.userName, cm.meetingName); } }
And now we have a fully qualified web api that can create a meeting. And we have swagger to test functions.
That’s good for a start…
Bingo for meetings–typescript making exe console–part 14
Bingo
Bingo is a small project, written in TypeScript , and developed with Alexandru Badita in launch break (one hour - more or less). You can find sources at https://github.com/alexandru360/PresentationBingoCards/ . Those are my blog posts for Bingo : ( scroll below for the post)Now it is the moment to have our first executable release– console application. First, we want to see if the js obtain by compilation of ts run under node ( it runs under ts-node index.ts , but it runs under node.js ? ). And we see that , when I run node index.js it gives error “ could not find bingo-meeting-object/MeetingFactory”.
It is clear that, even if yean workspaces works well with node and typescript, the final result, index.js , is not prepared to run under node. Solving the problem is about compiling typescript with project references . The documentation is at https://www.typescriptlang.org/docs/handbook/project-references.html#composite , and a sample project can be found at https://github.com/RyanCavanaugh/learn-a
It is composed by
1. having a tsconfig.json with
{
“compilerOptions”: {
“target”: “es5”,
“module”: “commonjs”,
“declaration”: true,
“declarationMap”: true,
“sourceMap”: true,
“strict”: false,
“composite”: true,
“esModuleInterop”: true
}
}
and extending in tsconfig.json
“extends”: “../tsconfig.settings.json”,
2. Compiling the projects with
tsc -b .
3. Creating index.ts with all classes exports
export * from “./MeetingsFactory”;
export * from “./Meeting”;
export * from “./Cards”;
export * from “./Participant”;
And now we can execute index.js with node index.jsinto
That means also the referenced projects are compiled into node_modules. That means that will not run without it.
We want now to create a console executable for the console project. That means something that compiles everything into an exe – no matter windows , linux , or macos
We use for that https://www.npmjs.com/package/pkg
In the package.json of the console project we put
“build” : “pkg dist/index.js -c package.json”
“scripts”: {“test”: “cd bingo-meeting-objects-test && yarn test”,“runConsole”: “cd bingo-meeting-console && yarn start”,“buildConsole”:”yarn build && cd bingo-meeting-console && yarn build”,“build”:”tsc -b .”}
FROM node:8
WORKDIR /app
COPY . ./
RUN yarn
RUN yarn buildConsole
CMD tail -f /dev/null
docker build .. -f docker_build_console.txt -t bingo_build_console
docker run -d –rm –name bingo_build_console_container bingo_build_console
docker cp bingo_build_console_container:/app/bingo-meeting-console/bingo-meeting-console-win.exe .
docker cp bingo_build_console_container:/app/bingo-meeting-console/bingo-meeting-console-linux .
docker cp bingo_build_console_container:/app/bingo-meeting-console/bingo-meeting-console-macos .
docker container kill bingo_build_console_container
Bingo for meetings–intermezzo – improving application–part 13
Bingo
Bingo is a small project, written in TypeScript , and developed with Alexandru Badita in launch break (one hour - more or less). You can find sources at https://github.com/alexandru360/PresentationBingoCards/ . Those are my blog posts for Bingo : ( scroll below for the post)After done with CLI, now it is time to improve a little bit the application.
1. should be more cards
For this I have replaced
let c=new Cards(); c.Name="Who just joined?"; c.Id = i++; ret.push(c); c=new Cards(); c.Name="Can you email that to everyone ?"; c.Id = i++; ret.push(c);
with a local function
let i=1; const ret=[]; let addCard = (name:string)=>{ let c=new Cards(); c.Name=name; c.Id = i++; ret.push(c); } addCard("Who just joined?"); addCard("Can you email that to everyone ?"); addCard("..., are you there ?"); addCard("Can you hear me?"); addCard("I'm sorry, I was on mute"); addCard("I'm sorry, connection issues"); addCard("Hello ? Hello ?"); addCard("Can we take this offline ?"); addCard("Can everyone see my screen ?"); addCard("No, still loading"); addCard("Sorry, I have to go to another call");
As a consequence, the pageSize for displayin via Inquirer.js should be make larger to display all items
2 . The cards should be sorted alphabetically ( easy: apply sort)
3. show cards checked by bingo when displaying again
4. add question to end meeting ( use null for card and a message ‘End meeting”)( should this be moved into a Display Layer?)
5.
show percentage at final ( calculate and add 2 tests for this )
6.show table with cards situation after meeting ( mapping the cards to columns ). Also, putting into evidence the ones checked by sorting after checked and then after name( should this be moved into a Display Layer?)
7.show current user name instead of asking for name( use username)
All those modifications, no matter how small they are, implies time to solve.And finding correct packages that will solve your problem.
Friday Links 332
Bingo for meetings- Adding a CLI application–part 12
Bingo
Bingo is a small project, written in TypeScript , and developed with Alexandru Badita in launch break (one hour - more or less). You can find sources at https://github.com/alexandru360/PresentationBingoCards/ . Those are my blog posts for Bingo : ( scroll below for the post)The easy way to test an application is to make a simple command line version . You can find the code at https://github.com/alexandru360/PresentationBingoCards/blob/master/bingo-meeting-console/index.ts
You can run also with Docker by running https://github.com/alexandru360/PresentationBingoCards/blob/master/dockerize/bingo_cli.bat
What were the steps ?
1. Install the @types/node, ts-node , typescript and others – see
2. Create an index.ts with the required CLI ( hint: prompt, figlet, chalk , username , inquirer,console.table are good to have) – read https://dev.to/hugodias/building-your-first-interactive-node-js-cli-1g2c
3. Created an async main() and calling with
(async () => { try { await main(); } catch (e) { console.log(JSON.stringify(e)); } })();
4. Modify package.json to have
“main”: “dist/index.js”,
“types”: “dist/index.d.ts”,
“scripts”: {
“start”: “ts-node index.ts”,
“build”: “tsc”,
“compile”: “tsc”
}
5. Put in the root package
“scripts”: {
“test”: “cd bingo-meeting-objects-test && yarn test”,
“runConsole”: “cd bingo-meeting-console && yarn start”
}
and then run yarn runConsole
I can say that the C# console experience is better 😉
You can download the source code from https://github.com/alexandru360/PresentationBingoCards/releases/tag/CLI
Bingo for meetings- yarn workspaces–part 11
Bingo
Bingo is a small project, written in TypeScript , and developed with Alexandru Badita in launch break (one hour - more or less). You can find sources at https://github.com/alexandru360/PresentationBingoCards/ . Those are my blog posts for Bingo : ( scroll below for the post)The problem that we see is how to have the same objects configured for backend and for frontend( e.g. a Meeting is used on the backend on the WebAPI to read from database and in the frontend to display)
In C# , there is the concept of dll / assembly that is common. In here we have the concept of yarn Workspaces : https://yarnpkg.com/lang/en/docs/cli/workspace/
What we want to achieve first is that the tests will be in a separate workspace bingo-meeting-objects-test , referencing the bingo-meeting-objects workspace
So, in order to do this, we have to modify :
- yarn workspaces to understand the structure and run tests
- bingo-meeting-objects to expose the result
- bingo-meeting-objects–test to import bingo-meeting-objects
- (depending on the projects) Other references : Modify docker bat file to consider the new structure
Let’s detail:
For yarn workspaces to understand the structure and run tests
So , first, we move the tests in a separate folder, bingo-meeting-objects–test , and we run nom init and add dependencies( jest, others)
Second, we add the yarn workspace package.json in the root with the following content:
{
“private”: true,
“workspaces”: [“bingo-cards-api”, “bingo-meeting-objects”]
}
“workspaces”: [“bingo-cards-api”, “bingo-meeting-objects”, “bingo-meeting-objects-test”],
“scripts”: {
“test”: “cd bingo-meeting-objects-test && yarn test”
}
}
In this manner, we can run yarn test from the root ( do not run yet!)
For bingo-meeting-objects to expose the result
In the tsconfig.json we put those lines:
“sourceMap”: true,
“declaration”: true,
In the package.json we modify to understand the declaration
“main”: “dist/index.js”,
“types”: “dist/index.d.ts”,“scripts”: {
“build”: “tsc”,
“compile”: “tsc”,
“test”: “jest”
},
For bingo-meeting-objects–test to import bingo-meeting-objects
We add jest and others. Also, we added dependency of bingo-meeting-objects:
“dependencies”: {
“bingo-meeting-objects”: “^1.0.0”,
Also, we need to modify the import of the test. Instead of the following line, when test was under subfolder test in the bingo-meeting-objects folder
import MeetingsFactory from ‘../MeetingsFactory’;
we put
import MeetingsFactory from “bingo-meeting-objects/MeetingsFactory”;
Now running yarn test in the root folder runs the test sucessfully
For (depending on the projects) Other references : Modify docker bat file to consider the new structure
We had the batch file that uses docker that was running the tests and then copy the results.
For start, we move the .dockerignore from the project to the root ( to not put node_modules)
Also, we modify how we copy the files to docker
For this, we modify this line
docker cp bingo_ci_test_container:/app/coverage/cobertura-coverage.xml .
into this line
docker cp bingo_ci_test_container:/app/bingo-meeting-objects-test/coverage/cobertura-coverage.xml .
to take into consideration the new structure
And that will be all! ( code source at https://github.com/alexandru360/PresentationBingoCards/releases/tag/yarnworkspaces )
Bingo for meetings- azure integrations–part 10
Bingo
Bingo is a small project, written in TypeScript , and developed with Alexandru Badita in launch break (one hour - more or less). You can find sources at https://github.com/alexandru360/PresentationBingoCards/ . Those are my blog posts for Bingo : ( scroll below for the post)Now it is about Continuous Integrations. We want tests to be run each time we push something to GitHub. For this we could use Azure DevOps. It is free for GitHub public repositories . We want to configure an azure pipeline to automatically run tests that we have in Docker.
So the pipeline will just have to explicit gather the test results ( tests + code coverage ) in order to display in the Azure Pipeline and in the project. Azure DevOps wants the test coverage in JaCoCo or Cobertura . Jest has Istanbul as default test coverage, and Istanbul has Cobertura report. So we modify the jest.config.js to support cobertura
module.exports = {
preset: ‘ts-jest’,
transform: {
‘^.+\\.tsx?$’: ‘ts-jest’,
},
testEnvironment: ‘node’,
collectCoverage: true,
coverageReporters : [“json”, “lcov”, “text”, “clover”,”cobertura”]
};
And to copy when docker building the tests to the local path
docker build ../Src -f docker_ci_test.txt -t bingo_ci_test
docker run -d –rm –name bingo_ci_test_container bingo_ci_test
docker cp bingo_ci_test_container:/app/jest-stare .
docker cp bingo_ci_test_container:/app/junit.xml .
docker cp bingo_ci_test_container:/app/coverage/cobertura-coverage.xml .
docker container kill bingo_ci_test_container
And then copy to the AzureDevOps test system
#https://docs.microsoft.com/en-us/azure/devops/pipelines/build/options?view=vsts&tabs=yaml
variables:
year: $(Date:yyyy)
month: $(Date:MM)
day: $(Date:dd)
uk: $(Date:yyyyMMdd)
messagePush: $(Build.SourceVersionMessage)
name: $(TeamProject)_$(BuildDefinitionName)_$(SourceBranchName)_$(Date:yyyyMMdd)$(Rev:.r)
jobs:
– job: FullTestOnLinux
pool:
vmImage: ‘ubuntu-16.04’
steps:
– checkout: self #skip checking out the default repository resource
clean: true
– script: |
cd dockerize
ls -l
chmod 777 ./ci_test.bat
./ci_test.bat
docker image ls
docker container ls
cp -r -v ./jest-stare $(Build.ArtifactStagingDirectory)/jest-stare/
cp ./junit.xml $(Build.ArtifactStagingDirectory)/junit.xml
cp ./cobertura-coverage.xml $(Build.ArtifactStagingDirectory)/cobertura-coverage.xml
displayName: test DDD
– task: PublishBuildArtifacts@1
inputs:
artifactName: Tests
displayName: ‘Publish Artifact: drop’
– task: PublishTestResults@2
inputs:
testRunner: JUnit
testResultsFiles: ‘$(Build.ArtifactStagingDirectory)/junit.xml’
– task: PublishCodeCoverageResults@1
inputs:
codeCoverageTool: ‘cobertura’
summaryFileLocation: ‘$(Build.ArtifactStagingDirectory)/cobertura-coverage.xml’
You can see the tests and the test coverage at https://dev.azure.com/ignatandrei0674/BingoAzureDevOps/_build/results?buildId=953&view=ms.vss-test-web.build-test-results-tab
Bingo for meetings- dockerize tests–part 9
Bingo
Bingo is a small project, written in TypeScript , and developed with Alexandru Badita in launch break (one hour - more or less). You can find sources at https://github.com/alexandru360/PresentationBingoCards/ . Those are my blog posts for Bingo : ( scroll below for the post)We have now full DDD and tests that should be run for the objects. However, we need a way to automatically have the tests run . The
easy way is to dockerize the tests – run in a container, grab the results, display somewhere.
First we should have the tests display in a nice form some data. For this, jest have the “reporters” features – but no documentation . So I try to find and https://github.com/dkelosky/jest-stare .
So what are the steps ?
- Create docker from node
- Copy sources ( add a .dockerignore to not copy node_modules)
- Install dependencies
- Run test
- run image into container and grab the tests results
The docker file , named docker_ci_test.txt , has the following content
FROM node:8
WORKDIR /app
COPY . ./
RUN yarn
RUN yarn test –reporters default jest-stare
CMD tail -f /dev/null
The bat that runs the image and grab results from the container
docker build ../src -f docker_ci_test.txt -t bingo_ci_test
docker run -d –rm –name bingo_ci_test_container bingo_ci_test
docker cp bingo_ci_test_container:/app/jest-stare .
docker container kill bingo_ci_test_container
Feel free to download the project from https://github.com/alexandru360/PresentationBingoCards/ and run the ci_test.bat file from dockerize folder.