Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 0 additions & 4 deletions .eslintignore

This file was deleted.

22 changes: 0 additions & 22 deletions .eslintrc.yml

This file was deleted.

46 changes: 35 additions & 11 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ jobs:
- uses: actions/setup-node@v4
with:
node-version-file: .nvmrc
cache: yarn
cache: npm

- run: yarn install --frozen-lockfile
- run: npm ci

- name: Lint sources
run: |
make lint
yarn lint
npm run lint

test:
runs-on: ubuntu-latest
Expand All @@ -45,21 +45,21 @@ jobs:
- uses: actions/setup-node@v4
with:
node-version-file: .nvmrc
cache: yarn
cache: npm


- name: Setup Go environment
uses: actions/setup-go@v5
with:
go-version: stable

- run: yarn install --frozen-lockfile
- run: npm ci

- name: Execute tests
run: |
make test
make test-integration
yarn test
npm test
make coverage

- name: SonarCloud Scan
Expand All @@ -76,19 +76,19 @@ jobs:
- uses: actions/checkout@v4

- id: extract_ref
run: echo ::set-output name=GIT_REF::$(echo ${GITHUB_REF##*/})
run: echo "GIT_REF=${GITHUB_REF##*/}" >> "$GITHUB_OUTPUT"

- uses: actions/setup-node@v4
with:
node-version-file: .nvmrc
cache: yarn
cache: npm

- name: Setup Go environment
uses: actions/setup-go@v5
with:
go-version: stable

- run: yarn install --frozen-lockfile
- run: npm ci

- name: Build
run: |
Expand All @@ -102,16 +102,40 @@ jobs:
name: smocker-bin
path: ./build/smocker.tar.gz

e2e:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version-file: .nvmrc
cache: npm

- name: Setup Go environment
uses: actions/setup-go@v5
with:
go-version: stable

- run: npm ci

- name: Install Playwright browser
run: npx playwright install --with-deps chromium

- name: Run Playwright non-regression suite
run: make test-e2e

deploy:
needs: [lint, test, build]
needs: [lint, test, build, e2e]
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4

- id: extract_ref
run: echo ::set-output name=GIT_REF::$(echo ${GITHUB_REF##*/})
run: echo "GIT_REF=${GITHUB_REF##*/}" >> "$GITHUB_OUTPUT"

- uses: actions/download-artifact@v4
with:
Expand Down
10 changes: 2 additions & 8 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
.DS_Store
.parcel-cache/
.vscode/
build/
coverage/
node_modules/
sessions
!tests/sessions
smocker
smocker.test
yarn-error.log
# All build, test and runtime output goes here (see Makefile / vite.config.ts / playwright.config.ts).
build/
43 changes: 35 additions & 8 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,36 @@
linters-settings:
lll:
line-length: 150
version: "2"

issues:
exclude-rules:
- text: "exported type .* should have comment or be unexported"
linters:
- go-lint
linters:
default: standard # errcheck, govet, ineffassign, staticcheck, unused
enable:
- lll
- misspell
settings:
lll:
line-length: 150
staticcheck:
checks:
- all
# ST1005: error strings should not be capitalized. Several validation errors are
# returned verbatim over the API (e.g. mock validation messages), so their exact,
# historically-capitalized wording is part of the observable contract and must not change.
- -ST1005
# ST1003 / ST1012: identifier naming conventions (e.g. Json vs JSON, ErrFoo error vars).
# These are long-standing internal identifiers; renaming them is pure churn with no
# effect on the mock format or HTTP API, so the existing names are kept for stability.
- -ST1003
- -ST1012
exclusions:
generated: lax
paths:
# node_modules ships a stray flatted/*.go; build is generated output. Neither is our code.
- node_modules
- build
presets:
- comments
- std-error-handling

formatters:
enable:
- gofmt
- goimports
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
16
24
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
ARG GO_VERSION=1.22
ARG GO_VERSION=1.26
FROM golang:${GO_VERSION}-alpine AS build-backend
RUN apk add --no-cache make
ARG VERSION=snapshot
Expand Down
63 changes: 44 additions & 19 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ REFLEX=$(GOPATH)/bin/reflex
$(REFLEX):
go install github.com/cespare/reflex@latest

GOLANGCILINTVERSION:=1.64.8
GOLANGCILINTVERSION:=2.12.2
GOLANGCILINT=$(GOPATH)/bin/golangci-lint
$(GOLANGCILINT):
curl -fsSL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(GOPATH)/bin v$(GOLANGCILINTVERSION)
curl -fsSL https://raw.githubusercontent.com/golangci/golangci-lint/v$(GOLANGCILINTVERSION)/install.sh | sh -s -- -b $(GOPATH)/bin v$(GOLANGCILINTVERSION)

VENOMVERSION:=v1.0.0-rc.6
VENOM=$(GOPATH)/bin/venom
Expand All @@ -48,22 +48,29 @@ GOCOVMERGE=$(GOPATH)/bin/gocovmerge
$(GOCOVMERGE):
go install github.com/wadey/gocovmerge@latest

CADDYVERSION:=v2.8.4
CADDY=$(GOPATH)/bin/caddy
$(CADDY):
cd /tmp; go get github.com/caddyserver/caddy/v2/...
go install github.com/caddyserver/caddy/v2/cmd/caddy@$(CADDYVERSION)

# All generated/runtime artifacts live under build/ so the repository root stays clean.
BUILD_DIR=build
SESSIONS_DIR=$(BUILD_DIR)/sessions
COVERAGE_DIR=$(BUILD_DIR)/coverage

.PHONY: persistence
persistence:
rm -rf ./sessions || true
cp -r tests/sessions sessions
rm -rf ./$(SESSIONS_DIR) || true
mkdir -p $(BUILD_DIR)
cp -r tests/sessions $(SESSIONS_DIR)

.PHONY: start
start: $(REFLEX) persistence
$(REFLEX) --start-service \
--decoration='none' \
--regex='\.go$$' \
--inverse-regex='^vendor|node_modules|.cache/' \
-- go run $(GO_LDFLAGS) main.go --log-level=$(LEVEL) --static-files ./build/client --persistence-directory ./sessions
-- go run $(GO_LDFLAGS) main.go --log-level=$(LEVEL) --static-files ./build/client --persistence-directory ./$(SESSIONS_DIR)

.PHONY: build
build:
Expand All @@ -79,15 +86,15 @@ format:

.PHONY: test
test:
mkdir -p coverage
go test -v -race -coverprofile=coverage/test-cover.out ./server/...
mkdir -p $(COVERAGE_DIR)
go test -v -race -coverprofile=$(COVERAGE_DIR)/test-cover.out ./server/...

PID_FILE=/tmp/$(APPNAME).test.pid
.PHONY: test-integration
test-integration: $(VENOM) check-default-ports persistence
mkdir -p coverage
go test -race -coverpkg="./..." -c . -o $(APPNAME).test
SMOCKER_PERSISTENCE_DIRECTORY=./sessions ./$(APPNAME).test -test.coverprofile=coverage/test-integration-cover.out >/dev/null 2>&1 & echo $$! > $(PID_FILE)
mkdir -p $(COVERAGE_DIR)
go test -race -coverpkg="./..." -c . -o $(BUILD_DIR)/$(APPNAME).test
SMOCKER_PERSISTENCE_DIRECTORY=./$(SESSIONS_DIR) $(BUILD_DIR)/$(APPNAME).test -test.coverprofile=$(COVERAGE_DIR)/test-integration-cover.out >/dev/null 2>&1 & echo $$! > $(PID_FILE)
sleep 5
$(VENOM) run tests/features/$(SUITE)
kill `cat $(PID_FILE)` 2> /dev/null || true
Expand All @@ -96,19 +103,36 @@ test-integration: $(VENOM) check-default-ports persistence
start-integration: $(VENOM)
$(VENOM) run tests/features/$(SUITE)

coverage/test-cover.out:
# End-to-end UI non-regression tests (Playwright). Builds the client and backend, serves the
# built client through smocker (seeded with tests/sessions), runs the suite, then stops the
# server. Requires the Playwright browser to be installed (npx playwright install chromium).
E2E_MOCK_PORT ?= 8080
E2E_ADMIN_PORT ?= 8081
.PHONY: test-e2e
test-e2e: build persistence
npm run build
SMOCKER_PERSISTENCE_DIRECTORY=./$(SESSIONS_DIR) ./$(BUILD_DIR)/$(APPNAME) \
--static-files ./$(BUILD_DIR)/client \
--mock-server-listen-port=$(E2E_MOCK_PORT) --config-listen-port=$(E2E_ADMIN_PORT) \
> $(BUILD_DIR)/e2e-smocker.log 2>&1 & \
SMK_PID=$$!; \
for i in $$(seq 1 30); do curl -sf localhost:$(E2E_ADMIN_PORT)/version >/dev/null 2>&1 && break; sleep 0.3; done; \
SMOCKER_E2E_URL=http://localhost:$(E2E_ADMIN_PORT) npx playwright test --config tests/e2e/playwright.config.ts; \
RC=$$?; kill $$SMK_PID 2>/dev/null || true; exit $$RC

$(COVERAGE_DIR)/test-cover.out:
$(MAKE) test

coverage/test-integration-cover.out:
$(COVERAGE_DIR)/test-integration-cover.out:
$(MAKE) test-integration

.PHONY: coverage
coverage: $(GOCOVMERGE) coverage/test-cover.out coverage/test-integration-cover.out
$(GOCOVMERGE) coverage/test-cover.out coverage/test-integration-cover.out > coverage/cover.out
coverage: $(GOCOVMERGE) $(COVERAGE_DIR)/test-cover.out $(COVERAGE_DIR)/test-integration-cover.out
$(GOCOVMERGE) $(COVERAGE_DIR)/test-cover.out $(COVERAGE_DIR)/test-integration-cover.out > $(COVERAGE_DIR)/cover.out

.PHONY: clean
clean:
rm -rf ./build ./coverage
rm -rf ./$(BUILD_DIR)

.PHONY: build-docker
build-docker:
Expand All @@ -133,9 +157,10 @@ optimize:

build/smocker.tar.gz:
$(MAKE) build
yarn install --frozen-lockfile --ignore-scripts
yarn build
cd build/; tar -czvf smocker.tar.gz *
npm ci --ignore-scripts
npm run build
# Package only the release artifacts, not test/runtime output that may also live in build/.
cd build/; tar -czvf smocker.tar.gz smocker client

.PHONY: release
release: build/smocker.tar.gz
Expand Down
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ The documentation is available on [smocker.dev](https://smocker.dev).
- [User Interface](#user-interface)
- [Usage](#usage)
- [Hello, World!](#hello-world)
- [Mock format schema](#mock-format-schema)
- [Development](#development)
- [Backend](#backend)
- [Frontend](#frontend)
Expand Down Expand Up @@ -133,6 +134,24 @@ curl -XPOST localhost:8081/reset

For more advanced usage, please read the [project's documentation](https://smocker.dev).

## Mock format schema

A JSON Schema describing the mock format lives at
[`docs/mock.schema.json`](./docs/mock.schema.json). It is generated from and kept in sync with the
Go types (`server/types`): the example mocks under `tests/data` are validated against it in CI, so
it stays accurate. The documentation references this file as the canonical schema.

Editors can use it for autocompletion and validation. With the YAML language server (VS Code,
Neovim, …), add this line at the top of a mocks file:

```yaml
# yaml-language-server: $schema=https://raw.githubusercontent.com/smocker-dev/smocker/main/docs/mock.schema.json
- request:
path: /hello
response:
body: '{"message": "Hello, World!"}'
```

## Development

### Backend
Expand Down
10 changes: 10 additions & 0 deletions client/components/App.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
// Base typography for the app: antd's reset leaves <body> without a font-size/family, so pin
// them here (otherwise the browser default 16px applies).
body {
font-size: 14px;
font-family:
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue",
Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
"Segoe UI Symbol", "Noto Color Emoji";
}

html,
body,
#root,
Expand Down
Loading
Loading