diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
new file mode 100644
index 0000000..9eedbc8
--- /dev/null
+++ b/.github/workflows/maven.yml
@@ -0,0 +1,36 @@
+# This workflow will build a Java project with Maven
+# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
+
+name: Java CI with Maven
+
+on:
+ push:
+ branches: [ main ]
+ pull_request:
+ branches: [ main ]
+ repository_dispatch:
+ types: contracts changed
+jobs:
+ build:
+ strategy:
+ matrix:
+ os: [ubuntu-latest, windows-latest, macos-latest]
+ java: [17]
+ runs-on: ${{ matrix.os }}
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ path: main
+ - name: Set up JDK ${{ matrix.java }}
+ uses: actions/setup-java@v3
+ with:
+ distribution: 'oracle'
+ java-version: ${{ matrix.java }}
+ - name: Build with Maven
+ working-directory: main
+ run: mvn test package jacoco:report
+ - name: Upload artifact
+ uses: actions/upload-artifact@v3
+ with:
+ name: jacoco coverage report
+ path: /home/runner/work/specmatic-api-coding-test/specmatic-api-coding-test/main/target/site/jacoco
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..6f8f362
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,8 @@
+target/*
+build/*
+.DS_Store
+lib/*
+*.iml
+*.idea
+.specmatic
+.vscode/*
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..1d2f105
--- /dev/null
+++ b/README.md
@@ -0,0 +1,92 @@
+# Specmatic Coding Test
+
+### Prerequisites:
+JDK 17+
+
+### Instructions:
+
+### 1. Clone this repository to your local machine.
+From a terminal, run the following command:
+```bash
+mvn clean test
+```
+You should see two failing tests:
+```bash
+[ERROR] Tests run: 2, Failures: 2, Errors: 0, Skipped: 0
+[INFO]
+[INFO] ------------------------------------------------------------------------
+[INFO] BUILD FAILURE
+[INFO] ------------------------------------------------------------------------
+```
+Your objective is to get these two tests to pass by following the rest of the instructions.
+
+### 2. Implement REST endpoints:
+This is a Kotlin based Spring Boot application.
+You are expected to implement the following endpoints to the **Products** controller:
+
+#### A. POST /products
+Implement a **POST** route ```/products``` which accepts a json payload.
+
+##### Request Schema:
+```json
+{
+ "name": "(string)",
+ "type": "(string enum)",
+ "inventory": "(integer)"
+}
+```
+The ```type``` field is an enum which can take the following values:
+```yaml
+ - gadget
+ - book
+ - food
+ - other
+```
+On successful creation of a product entity, the ```id``` of the created product should be returned:
+##### Response Schema:
+```json
+{
+ "id": "(integer)"
+}
+```
+
+
+
+
+#### B. GET /products
+Implement a **GET** route ```/products``` which accepts an **optional** query parameter called ```type```, which is an enum of the following values:
+```yaml
+ - gadget
+ - book
+ - food
+ - other
+```
+and returns a list of products with following schema.
+##### Response Schema:
+```json
+[
+ {
+ "id": "(integer)",
+ "name": "(string)",
+ "type": "(string enum)",
+ "inventory": "(integer)"
+ }
+]
+```
+
+### Note:
+- You are **not** expected to use a database.
+ You are free to use any datastructures like maps, lists, etc to store and retrieve products.
+
+- Writing any unit tests that you deem fit will be appreciated.
+
+- Please do not alter the following files:
+ - ContractTest.kt
+ - products_api.yaml
+ - specmatic.json
+
+### 3. Once you have both the tests passing, commit your changes and push to this repository.
+
+
+
+
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..1e84086
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,203 @@
+
+
+ 4.0.0
+
+ com.store
+ specmatic-api-coding-test
+ 1.0
+
+
+ 1.9.21
+ 17
+ 1.3.19
+ 3.2.5
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+ ${spring.boot.version}
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+ ${spring.boot.version}
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+ ${spring.boot.version}
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ ${spring.boot.version}
+ test
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ ${spring.boot.version}
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ 5.5.2
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ 5.5.2
+ test
+
+
+ org.junit.platform
+ junit-platform-runner
+ 1.6.0
+ test
+
+
+ org.junit.platform
+ junit-platform-engine
+ 1.6.0
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 2.22.2
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.1
+
+
+ in.specmatic
+ junit5-support
+ ${specmatic.version}
+ test
+
+
+ org.jetbrains.kotlin
+ kotlin-reflect
+ ${kotlin.version}
+
+
+ org.jetbrains.kotlin
+ kotlin-stdlib-jdk8
+ ${kotlin.version}
+
+
+ org.jetbrains.kotlin
+ kotlin-test-junit5
+ ${kotlin.version}
+ test
+
+
+
+
+
+
+ src/test/java
+
+ **/*.java
+
+
+
+ src/test/resources
+
+
+
+
+
+ org.jetbrains.kotlin
+ kotlin-maven-plugin
+ ${kotlin.version}
+
+
+ compile
+ process-sources
+
+ compile
+
+
+
+ test-compile
+ process-test-sources
+
+ test-compile
+
+
+
+
+ 17
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.1
+
+ UTF-8
+
+ ${maven.compiler}
+ -Werror
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 2.22.2
+
+ @{argLine} -Dfile.encoding=UTF-8
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ 2.3.4.RELEASE
+
+ true
+ com.store.Application
+
+
+
+
+ repackage
+
+
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ 0.8.8
+
+
+ jacoco-initialize
+
+ prepare-agent
+
+
+
+ report
+ prepare-package
+
+ report
+
+
+
+
+
+ **/DB.*
+ **/APIKeyAuthFilter.*
+
+
+
+
+
+
diff --git a/products_api.yaml b/products_api.yaml
new file mode 100644
index 0000000..f69de4a
--- /dev/null
+++ b/products_api.yaml
@@ -0,0 +1,130 @@
+openapi: 3.0.1
+info:
+ title: Order API
+ version: '2.0'
+servers:
+ - url: 'http://localhost:3000'
+paths:
+ /products:
+ get:
+ summary: GET Products based on type
+ parameters:
+ - name: type
+ in: query
+ schema:
+ type: string
+ enum:
+ - gadget
+ - book
+ - food
+ - other
+ examples:
+ GET_PRODUCTS:
+ value: 'gadget'
+ responses:
+ "200":
+ description: List of products in the response
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Product'
+ examples:
+ GET_PRODUCTS:
+ value:
+ - id: 1
+ name: 'XYZ Phone'
+ type: 'gadget'
+ inventory: 2
+ post:
+ summary: POST /products
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProductDetails'
+ examples:
+ CREATE_PRODUCT:
+ value:
+ name: iPhone
+ type: gadget
+ inventory: 100
+ responses:
+ "200":
+ description: POST /products
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProductId'
+ examples:
+ CREATE_PRODUCT:
+ value:
+ id: 1
+
+components:
+ schemas:
+ ProductDetails:
+ title: Product Details
+ type: object
+ properties:
+ name:
+ type: string
+ type:
+ $ref: '#/components/schemas/ProductType'
+ inventory:
+ type: integer
+ required:
+ - name
+ - type
+ - inventory
+ ProductType:
+ type: string
+ title: Product Type
+ enum:
+ - book
+ - food
+ - gadget
+ - other
+ ProductId:
+ title: Product Id
+ type: object
+ properties:
+ id:
+ type: integer
+ required:
+ - id
+ Product:
+ title: Product
+ allOf:
+ - $ref: '#/components/schemas/ProductId'
+ - $ref: '#/components/schemas/ProductDetails'
+ Products_RequestBody:
+ required:
+ - inventory
+ - name
+ - type
+ properties:
+ name:
+ type: string
+ type:
+ type: string
+ enum:
+ - gadget
+ - book
+ - food
+ - other
+ inventory:
+ type: number
+ ErrorResponseBody:
+ properties:
+ id:
+ type: number
+ timestamp:
+ type: string
+ status:
+ type: number
+ error:
+ type: string
+ message:
+ type: string
diff --git a/specmatic.json b/specmatic.json
new file mode 100644
index 0000000..4e3c572
--- /dev/null
+++ b/specmatic.json
@@ -0,0 +1,10 @@
+{
+ "sources": [
+ {
+ "provider": "filesystem",
+ "test": [
+ "products_api.yaml"
+ ]
+ }
+ ]
+}
diff --git a/src/main/java/com/store/MainApp.kt b/src/main/java/com/store/MainApp.kt
new file mode 100644
index 0000000..516676e
--- /dev/null
+++ b/src/main/java/com/store/MainApp.kt
@@ -0,0 +1,11 @@
+package com.store
+
+import org.springframework.boot.autoconfigure.SpringBootApplication
+import org.springframework.boot.runApplication
+
+@SpringBootApplication
+open class Application
+
+fun main(args: Array) {
+ runApplication(*args)
+}
\ No newline at end of file
diff --git a/src/main/java/com/store/controllers/Products.kt b/src/main/java/com/store/controllers/Products.kt
new file mode 100644
index 0000000..caaf695
--- /dev/null
+++ b/src/main/java/com/store/controllers/Products.kt
@@ -0,0 +1,9 @@
+package com.store.controllers
+
+import org.springframework.web.bind.annotation.RestController
+
+
+@RestController
+open class Products {
+
+}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
new file mode 100644
index 0000000..64545df
--- /dev/null
+++ b/src/main/resources/application.properties
@@ -0,0 +1,2 @@
+management.endpoints.web.exposure.include=*
+server.port=8090
\ No newline at end of file
diff --git a/src/test/java/com/store/ContractTest.kt b/src/test/java/com/store/ContractTest.kt
new file mode 100644
index 0000000..e52f237
--- /dev/null
+++ b/src/test/java/com/store/ContractTest.kt
@@ -0,0 +1,31 @@
+package com.store;
+
+import `in`.specmatic.test.SpecmaticContractTest
+import org.junit.jupiter.api.AfterAll
+import org.junit.jupiter.api.BeforeAll
+import org.springframework.boot.SpringApplication
+import org.springframework.context.ConfigurableApplicationContext
+
+//DO NOT ALTER
+class ContractTest : SpecmaticContractTest {
+ companion object {
+
+ private lateinit var context: ConfigurableApplicationContext
+
+ @JvmStatic
+ @BeforeAll
+ fun setUp() {
+ System.setProperty("host", "localhost");
+ System.setProperty("port", "8090");
+ System.setProperty("endpointsAPI", "http://localhost:8090/actuator/mappings");
+
+ context = SpringApplication.run(Application::class.java)
+ }
+
+ @JvmStatic
+ @AfterAll
+ fun tearDown() {
+ context.close();
+ }
+ }
+}
diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties
new file mode 100644
index 0000000..e30144c
--- /dev/null
+++ b/src/test/resources/application.properties
@@ -0,0 +1,3 @@
+server.port=8090
+management.endpoints.web.exposure.include=*
+endpointsAPI=http://localhost:8090/actuator/mappings
\ No newline at end of file