Merge remote-tracking branch 'origin/main' into workshop-unit-test-unfinished

This commit is contained in:
Arda Özdere 2023-04-04 12:00:39 +02:00
commit a6a946e4c2
15 changed files with 130 additions and 56 deletions

View file

@ -12,15 +12,18 @@ jobs:
if: ${{ github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'push' }}
steps:
- uses: google-github-actions/auth@v1
- name: Authenticate with Google Cloud
uses: google-github-actions/auth@v1
with:
credentials_json: '${{ secrets.GCP_SA_KEY }}'
- uses: google-github-actions/setup-gcloud@v1
- name: Setup gcloud CLI
uses: google-github-actions/setup-gcloud@v1
with:
project_id: ${{ secrets.GCP_PROJECT_ID }}
- run: |
- name: Deploy app to Cloud Run
run: |
gcloud run deploy my-finance-pal \
--image=${{ secrets.GCP_REGION }}-docker.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/cloud-run-source-deploy/my-finance-pal:${{ github.sha }} \
--allow-unauthenticated \

View file

@ -11,17 +11,22 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Checkout repository
uses: actions/checkout@v3
- uses: actions/setup-node@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- run: yarn install
- name: Install dependencies
run: yarn install
- run: yarn build
- name: Build application
run: yarn build
- run: yarn test
- name: Run unit tests
run: yarn test:unit
cloud_build:
needs: build_and_test
@ -29,17 +34,21 @@ jobs:
if: ${{ github.event_name == 'push' }}
steps:
- uses: actions/checkout@v3
- name: Checkout repository
uses: actions/checkout@v3
- uses: google-github-actions/auth@v1
- name: Authenticate with Google Cloud
uses: google-github-actions/auth@v1
with:
credentials_json: '${{ secrets.GCP_SA_KEY }}'
- uses: google-github-actions/setup-gcloud@v1
- name: Setup gcloud CLI
uses: google-github-actions/setup-gcloud@v1
with:
project_id: ${{ secrets.GCP_PROJECT_ID }}
- run: |
- name: Submit job to Cloud Build
run: |
gcloud builds submit \
--region=${{ secrets.GCP_REGION }} \
--config cloudbuild.yaml \

View file

@ -0,0 +1,9 @@
import baseConfig from "./jest.config"
import { type Config } from "jest";
const config: Config = {
...baseConfig,
testRegex: ".*\\.integration\\.spec\\.ts$",
}
export default config;

24
jest.config.ts Normal file
View file

@ -0,0 +1,24 @@
import { type Config } from "jest";
const config: Config = {
moduleFileExtensions: [
"js",
"json",
"ts"
],
rootDir: ".",
transform: {
"^.+\\.(t|j)s$": "ts-jest"
},
testEnvironment: "node",
roots: [
"<rootDir>/src/"
],
moduleDirectories: [
"node_modules",
"src"
],
setupFiles: ["./src/preStart.ts"]
}
export default config;

9
jest.config.unit.ts Normal file
View file

@ -0,0 +1,9 @@
import baseConfig from "./jest.config"
import { type Config } from "jest";
const config: Config = {
...baseConfig,
testRegex: ".*\\.unit\\.spec\\.ts$",
}
export default config;

View file

@ -13,7 +13,8 @@
"build": "run-s clean generate-api-types compile copy-resources",
"lint": "eslint --ext .ts src/",
"dev": "nodemon src/server.ts",
"test": "jest"
"test:unit": "jest --config \"jest.config.unit.ts\"",
"test:integration": "jest --config \"jest.config.integration.ts\""
},
"dependencies": {
"@types/supertest": "^2.0.12",
@ -60,26 +61,5 @@
"ts-node": "^10.9.1",
"tsconfig-paths": "^4.1.2",
"typescript": "^5.0.3"
},
"jest": {
"moduleFileExtensions": [
"js",
"json",
"ts"
],
"rootDir": ".",
"testRegex": ".*\\.spec\\.ts$",
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
},
"testEnvironment": "node",
"roots": [
"<rootDir>/src/"
],
"moduleDirectories": [
"node_modules",
"src"
],
"setupFiles": ["./src/preStart.ts"]
}
}

View file

@ -19,13 +19,16 @@ interface Args {
// **** Setup **** //
// Command line arguments
const args = parse<Args>({
env: {
type: String,
defaultValue: process.env.NODE_ENV ?? "development",
alias: "e",
const args = parse<Args>(
{
env: {
type: String,
defaultValue: process.env.NODE_ENV ?? "development",
alias: "e",
},
},
});
{ partial: true }
);
// Set the env file
const dotenvConfig = dotenv.config({

View file

@ -1,20 +1,35 @@
import { type BudgetSummary } from "../../domain/budget";
import type BudgetSummaryRepository from "../../repository/budget/budgetSummaryRepository";
import type BudgetUseCases from "./budgetUseCases";
import UUID from "../../domain/uuid";
import type BudgetRepository from "../../repository/budget/budgetRepository";
import { type Budget, type BudgetSummary } from "../../domain/budget";
import UUID from "../../domain/uuid";
export const createBudget: (
insertBudget: BudgetSummaryRepository["insert"]
) => BudgetUseCases["createBudget"] = (insertBudget) => async (newBudget) => {
const budgetSummary: BudgetSummary = {
...newBudget,
id: new UUID(),
spent: 0,
expenses: [],
type CreateBudgetUseCase = (
insertBudgetSummary: BudgetSummaryRepository["insert"]
) => BudgetUseCases["createBudget"];
export const createBudget: CreateBudgetUseCase =
(insertBudgetSummary) => async (newBudget) => {
// We could also create a class for our domain objects and put functionalities s.a.
// Budget.createFrom(newBudget) and BudgetSummary.getBudget() there
let budgetSummary: BudgetSummary = {
...newBudget,
id: new UUID(),
spent: 0,
expenses: [],
};
budgetSummary = await insertBudgetSummary(budgetSummary);
const createdBudget: Budget = {
id: budgetSummary.id,
spent: budgetSummary.spent,
name: budgetSummary.name,
limit: budgetSummary.limit,
startDate: budgetSummary.startDate,
endDate: budgetSummary.endDate,
};
return createdBudget;
};
return await insertBudget(budgetSummary);
};
export const getBudgetSummary: (
findBudget: BudgetSummaryRepository["find"]

View file

@ -1,16 +1,15 @@
import { createBudget } from "./budgetService";
import type BudgetUseCases from "./budgetUseCases";
import { type BudgetSummary, type NewBudget } from "../../domain/budget";
import { type Budget, type NewBudget } from "../../domain/budget";
import Limit from "../../domain/limit";
describe("budgetService", () => {
it("calls the create function with the correct object", async () => {
// GIVEN
const newBudget: NewBudget = { name: "My Budget", limit: new Limit(250) };
const expectedBudgetSummary: Omit<BudgetSummary, "id"> = {
const expectedBudget: Omit<Budget, "id"> = {
...newBudget,
spent: 0,
expenses: [],
};
const insertBudgetMock = jest.fn();
insertBudgetMock.mockImplementation((budgetSummary) => budgetSummary);
@ -23,7 +22,7 @@ describe("budgetService", () => {
// THEN
expect(insertedBudgetSummary).toEqual(
expect.objectContaining(expectedBudgetSummary)
expect.objectContaining(expectedBudget)
);
});
});

View file

@ -1,3 +1,7 @@
# The terraform code in this repo is based on the official tutorial from the following link
# https://cloud.google.com/blog/topics/developers-practitioners/easy-deployment-mean-stack-w-mongodb-atlas-cloud-run-and-hashicorp-terraform
# The rest of the steps can be followed up from there.
provider "mongodbatlas" {
public_key = var.atlas_pub_key
private_key = var.atlas_priv_key

View file

@ -1,3 +1,6 @@
# The terraform code in this repo is based on the official tutorial from the following link
# https://cloud.google.com/blog/topics/developers-practitioners/easy-deployment-mean-stack-w-mongodb-atlas-cloud-run-and-hashicorp-terraform
# The rest of the steps can be followed up from there.
resource "google_project_service" "ci_cd" {
project = google_project.prj.name
service = "${each.value}.googleapis.com"

View file

@ -1,3 +1,7 @@
# The terraform code in this repo is based on the official tutorial from the following link
# https://cloud.google.com/blog/topics/developers-practitioners/easy-deployment-mean-stack-w-mongodb-atlas-cloud-run-and-hashicorp-terraform
# The rest of the steps can be followed up from there.
provider "google" {}
resource "google_project" "prj" {

View file

@ -1,3 +1,7 @@
# The terraform code in this repo is based on the official tutorial from the following link
# https://cloud.google.com/blog/topics/developers-practitioners/easy-deployment-mean-stack-w-mongodb-atlas-cloud-run-and-hashicorp-terraform
# The rest of the steps can be followed up from there.
###-----------------------------------------------------------------------------
### configure terraform
###-----------------------------------------------------------------------------

View file

@ -1,3 +1,7 @@
# The terraform code in this repo is based on the official tutorial from the following link
# https://cloud.google.com/blog/topics/developers-practitioners/easy-deployment-mean-stack-w-mongodb-atlas-cloud-run-and-hashicorp-terraform
# The rest of the steps can be followed up from there.
output "app_url" {
value = google_cloud_run_service.app.status[0].url
}

View file

@ -1,3 +1,7 @@
# The terraform code in this repo is based on the official tutorial from the following link
# https://cloud.google.com/blog/topics/developers-practitioners/easy-deployment-mean-stack-w-mongodb-atlas-cloud-run-and-hashicorp-terraform
# The rest of the steps can be followed up from there.
###-----------------------------------------------------------------------------
### general config
###-----------------------------------------------------------------------------