Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
2b133e3
#129 Install openapi-generator-cli
pfwd Oct 2, 2022
1343aa8
#129 Updating docs structure
pfwd Oct 2, 2022
b8763e1
#129 adding openapi generator command
pfwd Oct 2, 2022
51b61be
#132 Adding created folder
pfwd Oct 2, 2022
55cea19
#129 updating command
pfwd Oct 3, 2022
9baa677
#129 Ingoring generated openapi file
pfwd Oct 3, 2022
ebdb144
#129 Merging main into branch
pfwd Oct 8, 2022
4241224
#129 Updating routes to use the endpoints generated by openapi
pfwd Oct 8, 2022
7547b94
#129 Removing created folder from gitignore
pfwd Oct 8, 2022
e17fd2e
#129 Removing Groups from API
pfwd Oct 8, 2022
6eb022f
#129 Removing Groups from API
pfwd Oct 8, 2022
3db8a22
#129 WIP Updating mockData to use the generated models (Only for HTML…
pfwd Oct 8, 2022
e2b349f
#129 WIP Altering mock data to match OpenAPI Spec
pfwd Oct 8, 2022
13e4910
#129 Fixing tests when using new openapi spec
pfwd Oct 9, 2022
8608d80
#129 Code formatting
pfwd Oct 9, 2022
d2fe7c4
#129 Setting shell parameter in tests
pfwd Oct 9, 2022
479857c
#129 Attempting to force failure
pfwd Oct 9, 2022
142105b
#129 This should fail
pfwd Oct 9, 2022
fdb046c
#129 Adding import checking
pfwd Oct 9, 2022
1acf167
#129 Adding shell
pfwd Oct 9, 2022
11af9c7
#129 Adding openapi workflow and adding spec file artifact
pfwd Oct 9, 2022
2175946
#129 Attempting to fix openapi github action
pfwd Oct 9, 2022
4bb6aa0
#129 Renaming test step to build step
pfwd Oct 9, 2022
a531bd2
#129 Adding tty
pfwd Oct 9, 2022
d1d276f
#129 Fixing openapi workflow
pfwd Oct 9, 2022
e61001c
#129 Downloading artifact from openapi workflow
pfwd Oct 9, 2022
6787cd8
#129 Generating Typescript API in workflow
pfwd Oct 9, 2022
53987a5
#129 Using a different download action
pfwd Oct 9, 2022
4abf719
#129 Updating path
pfwd Oct 9, 2022
ffcba93
#129 Removing working dir from api-client workflow
pfwd Oct 9, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .github/workflows/api-client.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,27 @@ jobs:
working-directory: ./api-client
run: cp .env.sample .env

- name: Download a openapi_spec
uses: dawidd6/action-download-artifact@v2
with:
name: openapi_spec_artifact
workflow: openapi.yaml
workflow_conclusion: success
path: ./docs/generated

- name: Generating Typescript API
working-directory: ./api-client
run: yarn run generate-api

- name: Lint
working-directory: ./api-client
run: yarn run lint
shell: bash

- name: Unit tests
working-directory: ./api-client
run: yarn run test
shell: bash

after-tests:
needs: tests # run after tests
Expand Down
98 changes: 98 additions & 0 deletions .github/workflows/openapi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# A lot of this was inspired by https://brunoscheufler.com/blog/2022-04-24-required-github-actions-jobs-in-a-monorepo

name: OpenAPI spec

on:
pull_request:
paths:
- 'api/src/Entity'
- '.github/workflows/openapi.yaml'
jobs:
change-detection:
runs-on: ubuntu-latest
outputs:
openapi: ${{ steps.changes.outputs.openapi }}
steps:
- uses: dorny/paths-filter@v2
id: changes
with:
list-files: shell
filters: |
openapi:
- 'api/src/Entity/**'
build:
needs: change-detection
if: needs.change-detection.outputs.openapi == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2

- name: Start the containers
working-directory: ./api
run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up -d --build

- name: Install composer packages
working-directory: ./api
run: docker-compose -f docker-compose.yml -f docker-compose.test.yml exec -T api composer install

- name: Run Database migrations
working-directory: ./api
run: docker-compose -f docker-compose.yml -f docker-compose.test.yml exec -T api bin/console --no-interaction doctrine:migration:migrate

- name: Generate openapi.yaml
working-directory: ./api
run: docker-compose exec -T api bash -c "bin/console api:openapi:export --yaml" > ../docs/generated/openapi.yaml

- name: Archive openapi artifacts
uses: actions/upload-artifact@v3
with:
name: openapi_spec_artifact
path: |
docs/generated

- name: Stop containers
working-directory: ./api
if: always()
run: docker-compose -f docker-compose.yml -f docker-compose.test.yml down

after-build:
needs: build # run after tests
runs-on: ubuntu-latest
if: success() # only run when all test have passed
# store success output flag for ci job
outputs:
success: ${{ steps.setoutput.outputs.success }}
steps:
- id: setoutput
run: echo "::set-output name=success::true"

dummy-step:
runs-on: ubuntu-latest
needs: change-detection
# runs if API was not changed
if: needs.change-detection.outputs.openapi == 'false'
outputs:
success: ${{ steps.setoutput.outputs.success }}
steps:
- id: setoutput
run: echo "::set-output name=success::true"


# step that will be used for required status check
# make sure it has a unique name! this will always run, but
# after the tests & after-tests steps or the dummy step in case
# the API was not modified
ci_openapi:
runs-on: ubuntu-20.04
if: always()
needs: [build, after-build, dummy-step]
steps:
- run: |
passed="${{ needs.after-build.outputs.success || needs.dummy-step.outputs.success }}"
if [[ $passed == "true" ]]; then
echo "Build passed"
exit 0
else
echo "Build failed"
exit 1
fi
7 changes: 5 additions & 2 deletions api-client/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
module.exports = {
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended'
'plugin:@typescript-eslint/recommended',
'plugin:import/recommended',
'plugin:import/typescript'
],
parser: '@typescript-eslint/parser',
plugins: [
'@typescript-eslint'
'@typescript-eslint',
'import'
],
root: true,
ignorePatterns: [
Expand Down
3 changes: 2 additions & 1 deletion api-client/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
node_modules
coverage
.env
.env
src/generated
2 changes: 1 addition & 1 deletion api-client/jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type {Config} from '@jest/types';

const config: Config.InitialOptions = {
collectCoverage: true,
collectCoverageFrom: ["./src/**", "./mockData/**", "!./src/routes.json"],
collectCoverageFrom: ["./src/**", "!./src/generated/openapi/**", "./mockData/**", "!./src/routes.json"],
testPathIgnorePatterns: ["./src/routes.json"],
// TODO #88 https://github.com/howToCodeWell/code-quiz/issues/88
// This needs to be un-commented once we reach 90% code coverage
Expand Down
7 changes: 7 additions & 0 deletions api-client/openapitools.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"$schema": "./node_modules/@openapitools/openapi-generator-cli/config.schema.json",
"spaces": 2,
"generator-cli": {
"version": "6.2.0"
}
}
6 changes: 5 additions & 1 deletion api-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,18 @@
"scripts": {
"start": "npx ts-node src/server.ts",
"lint": "eslint .",
"test": "jest"
"test": "jest",
"generate-api": "rm -rf src/generated/openapi; openapi-generator-cli generate -i ../docs/generated/openapi.yaml -g typescript-axios -o src/generated/openapi --additional-properties=npmName=restClient,supportsES6=true,npmVersion=8.19.1,withInterfaces=true,typescriptThreePlus=true"
},
"devDependencies": {
"@openapitools/openapi-generator-cli": "^2.5.2",
"@types/jest": "^29.0.3",
"@types/json-server": "^0.14.4",
"@typescript-eslint/eslint-plugin": "^5.38.1",
"@typescript-eslint/parser": "^5.38.1",
"eslint": "^8.24.0",
"eslint-import-resolver-typescript": "^3.5.1",
"eslint-plugin-import": "^2.26.0",
"jest": "^29.0.3",
"json-server": "^0.17.0",
"ts-jest": "^29.0.2"
Expand Down
28 changes: 18 additions & 10 deletions api-client/src/api/apiClient.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
import axios from "axios";
import * as dotenv from "dotenv"

import {Configuration, QuestionApi, QuizApi} from "../generated/openapi/"

dotenv.config()

export const axiosClient = axios.create({
baseURL: `${process.env.API_BASE_PATH}:${process.env.API_PORT}`,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
const configuration = new Configuration({
basePath: `${process.env.API_BASE_PATH}:${process.env.API_PORT}`,
baseOptions: {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
}
});
})

const apiClient = {
quizAPI: new QuizApi(configuration),
questionAPI: new QuestionApi(configuration),
configuration: configuration
}

export default {
axiosClient
};
export default apiClient
12 changes: 11 additions & 1 deletion api-client/src/api/mockClient.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as dotenv from "dotenv"
import * as jsonServer from "json-server"
import data from "../mockData"
import routes from "../routes.json"
import data from "../mockData";

export function mockApp() {
dotenv.config()
Expand All @@ -14,6 +14,16 @@ export function mockApp() {
const router = jsonServer.router(data)
const middlewares = jsonServer.defaults()

server.get('/quiz/*', (req, res) => {
const id = (req.params[0])
res.jsonp(data.quiz[id -1])
})

server.get('/question/*', (req, res) => {
const id = (req.params[0])
res.jsonp(data.question[id -1])
})

server.use(middlewares)
server.use(router)
return server.listen(process.env.API_PORT)
Expand Down
5 changes: 5 additions & 0 deletions api-client/src/api/requestHandlers/questionRequest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import apiClient from "../apiClient";

export function getById(id: string) {
return apiClient.questionAPI.apiQuestionIdGet(id)
}
8 changes: 6 additions & 2 deletions api-client/src/api/requestHandlers/quizRequest.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import {axiosClient} from "../apiClient";
import apiClient from "../apiClient";

export function getById(id: string) {
return apiClient.quizAPI.apiQuizIdGet(id)
}

export function getAll() {
return axiosClient.get('/quiz')
return apiClient.quizAPI.apiQuizzesGetCollection()
}
54 changes: 0 additions & 54 deletions api-client/src/mockData/htmlQuiz/htmlAnswers.ts

This file was deleted.

61 changes: 54 additions & 7 deletions api-client/src/mockData/htmlQuiz/htmlQuestions.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,63 @@
import {QuestionDTO} from "../../model/QuestionDTO"
import {HTMLAnswerOne, HTMLAnswerTwo} from "./htmlAnswers";
import {QuestionJsonldQuestionRead} from "../../generated/openapi"

const HTMLQuestions: QuestionDTO[] = [
const HTMLQuestions: QuestionJsonldQuestionRead[] = [
{
id: "1",
'@context': "/api/v1/contexts/Question",
'@id': "/api/v1/question/1",
'@type': "Question",
content: "What is the <aside> tag for?",
answers: HTMLAnswerOne,
answers: [
{
'@id': "/api/v1/answers/1",
'@type': "Answer",
content: "Primary content",
is_correct: false,
},
{
'@id': "/api/v1/answers/2",
'@type': "Answer",
content: "Empty content",
is_correct: false,
},
{
'@id': "/api/v1/answers/3",
'@type': "Answer",
content: "Indirectly related content",
is_correct: true,
},
],
},
{
id: "2",
'@context': "/api/v1/contexts/Question",
'@id': "/api/v1/question/2",
'@type': "Question",
content: "How many HTML heading levels are there?",
answers: HTMLAnswerTwo,
answers: [
{
'@id': "/api/v1/answers/4",
'@type': "Answer",
content: "Primary content",
is_correct: false,
},
{
'@id': "/api/v1/answers/5",
'@type': "Answer",
content: "Answer",
is_correct: true,
},
{
'@id': "/api/v1/answers/6",
'@type': "Answer",
content: "Indirectly related content",
is_correct: false,
},
{
'@id': "/api/v1/answers/7",
'@type': "Answer",
content: "Unlimited",
is_correct: false,
},
],
},
]

Expand Down
Loading