mirror of
https://gitcode.com/GitHub_Trending/az/azerothcore-wotlk.git
synced 2026-10-10 07:06:38 +08:00
test(e2e): review, flakes, no unsolicited e2e (#27514)
Co-authored-by: sudlud <[email protected]>
This commit is contained in:
co-authored by
sudlud
parent
862a6615e6
commit
19ca6e1128
+20
-15
@@ -1,6 +1,13 @@
|
||||
# E2E policy
|
||||
|
||||
Mandatory when writing or changing live-stack e2e (`e2e/`). **When** to write tests. **How:** AzerothGhost `LLM_GUIDE.md` / `EXAMPLES.md` (this file does not replace them). Inventory: `e2e/README.md`. Stack: AC 3.3.5a auth+world+MySQL; `E2E_*` may point at a gateway.
|
||||
**Do not add, promote, or invent live-stack e2e tests unless the user explicitly asked.**
|
||||
Do not write `e2e/local/` scratch tests to validate a fix. Existing tests that fail after a
|
||||
behaviour change may be updated. Scratch, if any, stays in `e2e/local/` (gitignored) and is
|
||||
never committed. Do not mention missing coverage unless the user asked about it.
|
||||
|
||||
The rest of this file applies only when the user asked to change `e2e/`, or an existing test
|
||||
broke. **How:** AzerothGhost `LLM_GUIDE.md` / `EXAMPLES.md` (this file does not replace them).
|
||||
Inventory: `e2e/README.md`. Stack: AC 3.3.5a auth+world+MySQL; `E2E_*` may point at a gateway.
|
||||
|
||||
## Terms
|
||||
|
||||
@@ -19,17 +26,15 @@ First match wins:
|
||||
| If | Then |
|
||||
|----|------|
|
||||
| Pure calc / parse / bit math / no world | UNIT. NEVER e2e. |
|
||||
| Covered by existing unit/mocks (`SpellProc*`, …) without login/map/DBC fidelity | UNIT or in-process integration. E2E only if unit cannot reach the path. |
|
||||
| Covered by existing unit/mocks (`SpellProc*`, …) without login/map/DBC fidelity | UNIT or in-process integration. No new e2e unless asked. |
|
||||
| SQL-only static (text, displayid, non-script loot) | No e2e. Manual optional. |
|
||||
| SmartAI / conditions / waypoints; outcome only in-world | E2E SHOULD if player-visible and deterministic; else document manual repro. |
|
||||
| Multi-system on a live session, or protocol/client-observed, or player-repro bugfix | E2E MUST (or update existing). Unit MAY still cover pure pieces. |
|
||||
| Refactor, no behaviour intent | Update tests that break. Add e2e only if a critical system below lacks an oracle. |
|
||||
| SmartAI / conditions / waypoints; outcome only in-world | No new e2e unless asked. Document a manual repro if useful. |
|
||||
| Multi-system on a live session, or protocol/client-observed, or player-repro bugfix | No new e2e unless asked. Unit MAY still cover pure pieces. |
|
||||
| Refactor, no behaviour intent | Update tests that break. Do not add e2e. |
|
||||
|
||||
Bias: player-visible and MVT fits → prefer e2e over unit-only. Not a MUST trigger and unsure → do not invent e2e; file a gap.
|
||||
Do not invent e2e because a change is player-visible. File a gap only if the user asked for coverage.
|
||||
|
||||
**MUST add or update e2e** when any of: player-visible bugfix (encode the repro); protocol change; multi-system (combat/aura/death/quest/loot/mount/pet/vehicle/instance/PvP/guild/relog/DB after `.save`); crash/hang/freeze on client action (`ProbeWorldAlive` / `AssertWorldAlive`); existing `TestAC_*` path touched (update, do not drop); critical system with no oracle; claimed blizzlike fix for a tracked issue (`ConfirmedBugf` until fixed).
|
||||
|
||||
**MUST NOT** treat “tested in-game” as a substitute when MVT is feasible.
|
||||
**Update** an existing test when the user asked or that test broke. Do not add a new suite, `TestAC_*`, or `e2e/local/` scratch test unless the user asked.
|
||||
|
||||
Harness cannot express it: extend harness or file a harness gap; inventory the gap; still unit-test pure logic.
|
||||
|
||||
@@ -106,7 +111,7 @@ Use these, not bare `t.Fatalf`, for classified outcomes:
|
||||
|
||||
## Critical systems
|
||||
|
||||
A PR that implements, fixes, or refactors a row MUST add or update e2e for that oracle, or keep an existing test that still asserts it. If harness cannot: gap in `e2e/README.md` + unit for pure logic.
|
||||
Do not add e2e for a row just because a PR touches that system. Update an existing test only if it broke or the user asked. If harness cannot express something the user asked for: gap in `e2e/README.md` + unit for pure logic.
|
||||
|
||||
| System | Oracle / drive |
|
||||
|--------|----------------|
|
||||
@@ -129,11 +134,11 @@ Search consumer suite + Ghost `examples/` + `TestAC_*` for issue, spell, quest,
|
||||
|
||||
Same oracle → same test (extend / table-drive). Same setup, different oracle → helper or `t.Run`, not a second login. NEVER copy Ghost `examples/` without changing the oracle. One tracked issue → one primary `TestAC_<id>_…`; extra edges as `t.Run` or siblings only if isolation requires. Same root cause + same assertion surface → merge.
|
||||
|
||||
Inventory (`e2e/README.md` + suite comments): category, one-sentence oracle, P0–P3, `covered` (test name) / `gap` / `blocked-harness` / `manual-only`, issue links, note. MUST update when adding coverage or finding a gap. `blocked-harness` MUST name the missing API (opcode, waiter, multi-realm, …). Closing a P0/P1 gap is preferred when touching that subsystem. When pruning, merge redundant tests and refresh the inventory.
|
||||
Inventory (`e2e/README.md` + suite comments): category, one-sentence oracle, P0–P3, `covered` (test name) / `gap` / `blocked-harness` / `manual-only`, issue links, note. Update it when the user asked you to add or remove coverage. `blocked-harness` MUST name the missing API (opcode, waiter, multi-realm, …). When pruning, merge redundant tests and refresh the inventory.
|
||||
|
||||
Prefer one solid test per merged player-visible bugfix. Deepen critical categories over new weak ones. Every test: unique oracle + owner (issue or feature). Delete or merge tests that no longer map to a behaviour.
|
||||
Do not add a test per bugfix. Every existing test: unique oracle + owner (issue or feature). Delete or merge tests that no longer map to a behaviour.
|
||||
|
||||
## Priority (next test)
|
||||
## Priority (only if the user asked for a new test)
|
||||
|
||||
Highest feasible MVT:
|
||||
|
||||
@@ -144,7 +149,7 @@ Highest feasible MVT:
|
||||
| **P2** | Single-boss timers/waves/targeting; guild charter/bank; multi-bot PvP; realm-scoped GM / persisted visibility |
|
||||
| **P3** | QoL, display, nondeterministic farm; full raid clears (out of default growth) |
|
||||
|
||||
On a PR: implement e2e for the highest-priority trigger the PR activates. Do not add P3 in the same change unless asked.
|
||||
On a PR: do not add e2e unless the user asked. If they did, pick the highest-priority trigger they named. Do not add P3 in the same change unless asked.
|
||||
|
||||
## Isolation, comments, flakes
|
||||
|
||||
@@ -167,6 +172,6 @@ NEVER let a test PASS while the product oracle is wrong. NEVER multi-retry + sof
|
||||
|
||||
Update tests in the same PR as the behaviour change. Harness renames: update consumers in the same landing window. Ghost `e2e/examples/` are patterns; AC regressions live in the consumer suite.
|
||||
|
||||
Scratch MUST be `e2e/local/` (gitignored except `local/README.md`). NEVER commit throwaways. Promote into `e2e/suites/` next to related tests in the same PR as the fix. Prefer live e2e over ad-hoc GM when the stack is up.
|
||||
Scratch MUST be `e2e/local/` (gitignored except `local/README.md`). NEVER commit throwaways. Do not promote scratch into `e2e/suites/` unless the user asked.
|
||||
|
||||
Local (from `e2e/`): `go test -tags=e2e ./...`. Official-repo PR and master CI: full suite after nopch clang-18 (reuses those binaries). Dispatch `-f scope=smoke` for a smaller run. Touch `.github/workflows/e2e-live.yml` only when changing CI.
|
||||
|
||||
@@ -54,7 +54,7 @@ on:
|
||||
required: false
|
||||
default: '1'
|
||||
timeout:
|
||||
description: 'go test -timeout (smoke default 30m; full should be >=120m)'
|
||||
description: 'go test -timeout (smoke default 30m; full default 60m; job ceiling 90m)'
|
||||
required: false
|
||||
default: ''
|
||||
parallel:
|
||||
@@ -86,11 +86,16 @@ env:
|
||||
jobs:
|
||||
e2e:
|
||||
name: e2e (native / ${{ inputs.scope || 'full' }})
|
||||
# github.repository is the base repo on pull_request, so fork PRs still run here.
|
||||
# This only skips the job inside a fork's own CI.
|
||||
if: github.repository == 'azerothcore/azerothcore-wotlk'
|
||||
# Artifact path (PR nopch): ubuntu-24.04 to match the uploaded binaries.
|
||||
# Dispatch (no artifact): optional self-hosted via E2E_RUNS_ON.
|
||||
# Ephemeral runners only: MySQL grants persist accounts, and Stop servers
|
||||
# pkill env/dist/bin/worldserver and authserver.
|
||||
runs-on: ${{ inputs.artifact_run_id != '' && 'ubuntu-24.04' || vars.E2E_RUNS_ON || 'ubuntu-24.04' }}
|
||||
timeout-minutes: 480
|
||||
# Real ceiling. go test -timeout is per package (full default 60m).
|
||||
timeout-minutes: 90
|
||||
steps:
|
||||
- name: Free disk
|
||||
run: |
|
||||
@@ -108,6 +113,17 @@ jobs:
|
||||
go-version-file: e2e/go.mod
|
||||
cache-dependency-path: e2e/go.sum
|
||||
|
||||
- name: Check gofmt
|
||||
working-directory: e2e
|
||||
run: |
|
||||
set -euo pipefail
|
||||
dirty="$(gofmt -l .)"
|
||||
if [[ -n "${dirty}" ]]; then
|
||||
echo "::error::gofmt needed"
|
||||
printf '%s\n' "${dirty}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# AzerothGhost is a public Go module (e2e/go.mod; repo azerothcore/AzerothGhost).
|
||||
- name: Download e2e modules
|
||||
working-directory: e2e
|
||||
@@ -360,7 +376,7 @@ jobs:
|
||||
|| { echo "bad timeout duration: ${E2E_TIMEOUT_INPUT}"; exit 1; }
|
||||
timeout="${E2E_TIMEOUT_INPUT}"
|
||||
elif [[ "${scope}" == "full" ]]; then
|
||||
timeout="180m"
|
||||
timeout="60m"
|
||||
else
|
||||
timeout="30m"
|
||||
fi
|
||||
|
||||
@@ -7,8 +7,7 @@ AzerothCore is a C++ MMORPG server emulator for World of Warcraft 3.3.5a (WotLK)
|
||||
- **Do not configure or build unless explicitly asked.** Builds are slow and rarely needed for code changes.
|
||||
- **Never edit SQL files outside `data/sql/updates/pending_db_*/` unless explicitly requested.** `data/sql/base/`, `data/sql/archive/`, and `data/sql/updates/db_*/` are immutable.
|
||||
- Formatting follows `.editorconfig`: UTF-8, LF, max 120 cols, trailing newline, no trailing whitespace; 4-space indent for C++ (tabs forbidden), 2-space for JSON/YAML/sh/ts/js.
|
||||
- **Prefer live-stack e2e to debug/validate player-visible behaviour** when a local auth+world+MySQL stack is available (protocol, combat, quests, loot, death, multi-bot). See `e2e/README.md` and AzerothGhost `e2e/LLM_GUIDE.md`. Do not invent e2e for pure unit-sized logic — see `.agents/docs/e2e-policy.md`.
|
||||
- **Scratch e2e only under `e2e/local/`** (gitignored). Never commit throwaway debug tests. Promote keepers into `e2e/suites/` or `e2e/smoke/`.
|
||||
- **Do not write or add live-stack e2e tests unless the user explicitly asks.** Do not create `e2e/local/` scratch tests to validate a fix. Existing `e2e/` tests that break after a change may be updated. Do not mention missing coverage unless the user asked about it.
|
||||
- Planning docs go in `.agents/plans/<task-slug>/` (gitignored), named `<task-slug>.<TYPE>.md` (`PLAN`, `REQUIREMENTS`, `ANALYSIS`, …).
|
||||
- **Credit upstream authors.** Code, a mechanism, or data mirrored from another core (TrinityCore, cMaNGOS, …) is committed with `--author` naming the original commit's author (extra sources as `Co-authored-by`), even when rewritten against AC or confirmed by own sniffs; find them in the upstream file's commit history.
|
||||
|
||||
@@ -24,7 +23,7 @@ Read the matching doc(s) BEFORE starting the task:
|
||||
- Reviewing a changeset or PR → `.agents/docs/code-review.md`
|
||||
- Self-reviewing, or opening or updating a PR → also `.agents/docs/self-review-rules.md`
|
||||
- Touching a subsystem that has a doc in `.agents/docs/systems/` → read that doc too
|
||||
- Writing, debugging, or changing live-stack e2e (`e2e/`) → `e2e/README.md`, `.agents/docs/e2e-policy.md`, and AzerothGhost `e2e/LLM_GUIDE.md` (scratch work → `e2e/local/`)
|
||||
- Changing existing live-stack e2e (`e2e/`), and only when the user asked or an existing test broke → `e2e/README.md` and `.agents/docs/e2e-policy.md`
|
||||
- Capturing a lesson or adding/updating agent docs → `.agents/docs/README.md`
|
||||
|
||||
## Repository layout
|
||||
@@ -36,7 +35,7 @@ Read the matching doc(s) BEFORE starting the task:
|
||||
- `src/server/shared/` — code shared by auth and world servers.
|
||||
- `src/server/apps/{authserver,worldserver}/` — entry points (ports 3724 and 8085).
|
||||
- `src/test/` — unit tests + mocks.
|
||||
- `e2e/` — live-stack Go e2e (AzerothGhost harness); see `e2e/README.md`. Scratch/debug tests: `e2e/local/` (gitignored).
|
||||
- `e2e/` — live-stack Go e2e (AzerothGhost harness); see `e2e/README.md`.
|
||||
- `data/sql/` — `base/` (historical schema), `updates/db_*/` (merged), `updates/pending_db_*/` (in-flight), `custom/` (gitignored).
|
||||
- `modules/` — external modules (see below).
|
||||
- `apps/` — helper scripts; `apps/codestyle/` holds the lint scripts.
|
||||
|
||||
+10
-11
@@ -6,13 +6,13 @@ and run against a **live** authserver + worldserver + MySQL.
|
||||
|
||||
Offline `go test ./...` (without `-tags=e2e`) skips these packages.
|
||||
|
||||
Authoring rules for new tests live in the harness:
|
||||
Authoring rules for the existing suite live in the harness:
|
||||
|
||||
| Doc | Audience |
|
||||
|-----|----------|
|
||||
| [LLM_GUIDE.md](https://github.com/azerothcore/AzerothGhost/blob/v1.0.8/e2e/LLM_GUIDE.md) | Compact MUST/NEVER + APIs (LLMs and humans) |
|
||||
| [LLM_GUIDE.md](https://github.com/azerothcore/AzerothGhost/blob/v1.0.8/e2e/LLM_GUIDE.md) | Compact MUST/NEVER + APIs |
|
||||
| [EXAMPLES.md](https://github.com/azerothcore/AzerothGhost/blob/v1.0.8/e2e/EXAMPLES.md) | Full recipes and skeletons |
|
||||
| `.agents/docs/e2e-policy.md` | When to add e2e vs unit tests (agent/review policy) |
|
||||
| `.agents/docs/e2e-policy.md` | Do not add e2e unless asked; suite conventions |
|
||||
|
||||
---
|
||||
|
||||
@@ -127,19 +127,16 @@ go test -tags=e2e ./suites/... -run TestPets_SummonWaitDismiss -count=1 -v -time
|
||||
|
||||
Every live test uses `//go:build e2e` and should call `meta.Begin(t, meta.TestMeta{…})` before expensive setup.
|
||||
|
||||
### Scratch / agent debug (`local/`)
|
||||
### Scratch (`local/`)
|
||||
|
||||
When validating a fix on a **live** stack (player-visible combat, protocol, quests, multi-bot), prefer writing a small e2e under **`e2e/local/`** instead of ad-hoc GM spam or long manual checklists. That tree is **not committed**.
|
||||
`e2e/local/` is gitignored except `local/README.md`. Do not add tests there unless asked. If something is already there:
|
||||
|
||||
```bash
|
||||
# create e.g. local/repro/repro_e2e_test.go (//go:build e2e)
|
||||
make e2e-local
|
||||
# or:
|
||||
go test -tags=e2e ./local/... -count=1 -v -timeout 30m -parallel 1
|
||||
```
|
||||
|
||||
If the scenario should stay as a regression, **move** it into `suites/` next to related tests with proper `meta.Begin` tags — see `.agents/docs/e2e-policy.md`.
|
||||
|
||||
### Inventory
|
||||
|
||||
| Category | Oracle | Pri | Coverage | Issue |
|
||||
@@ -349,9 +346,11 @@ A test that fails intermittently on a **correct** core is a test/harness bug unt
|
||||
|
||||
---
|
||||
|
||||
## Policy (when to add e2e)
|
||||
## Policy
|
||||
|
||||
Use `.agents/docs/e2e-policy.md` for decision trees (e2e vs unit, mandatory triggers, MVT). This README is **how to run and structure** the suite; the harness guides are **how to author** scenarios.
|
||||
Do not add e2e tests unless asked. Do not mention missing coverage unless the user asked about it.
|
||||
`.agents/docs/e2e-policy.md` is suite convention when changing existing tests. This README is
|
||||
**how to run and structure** the suite.
|
||||
|
||||
---
|
||||
|
||||
@@ -367,6 +366,6 @@ Details live in the workflow files only:
|
||||
| Merge to `master` | same clang-18 nopch build, then **full** e2e again (flake + merge-base drift) |
|
||||
| Actions → **e2e-live** → Run workflow (official repo; needs workflow on default branch, or `gh workflow run … --ref e2e`) | Compiles on the runner; choose scope (smoke/full) |
|
||||
|
||||
Day-to-day development and agent debugging should use a **local** stack + `e2e/local/` or the committed suites — not CI setup docs.
|
||||
Day-to-day development should use a **local** stack and the committed suites, not CI setup docs.
|
||||
|
||||
Greppable failure prefixes: `precondition:`, `AC#N CONFIRMED BUG:`, `harness:`, `WARNING:`.
|
||||
|
||||
+2
-45
@@ -1,15 +1,7 @@
|
||||
# e2e/local — scratch / debug tests (not committed)
|
||||
|
||||
Put **throwaway** live-stack tests here while debugging a core/script change.
|
||||
Everything under this directory is **gitignored** except this README.
|
||||
|
||||
## When to use
|
||||
|
||||
| Put it here | Promote to |
|
||||
|-------------|------------|
|
||||
| One-off repro while fixing a bug | `suites/…` or `suites/issues/` once it should stay green |
|
||||
| Agent exploratory scenario | Same — only keep if policy says e2e is warranted |
|
||||
| Experiments with harness APIs | Drop or move when done |
|
||||
Do not add tests here unless asked. Do not promote scratch into `smoke/` or `suites/` unless asked.
|
||||
|
||||
Do **not** put permanent regressions here; CI and reviewers only look at `smoke/` and `suites/`.
|
||||
|
||||
@@ -21,43 +13,8 @@ From `e2e/` with stack up and `E2E_*` set (see parent [README.md](../README.md))
|
||||
# all scratch packages
|
||||
go test -tags=e2e ./local/... -count=1 -v -timeout 30m -parallel 1
|
||||
|
||||
# one file’s package (create local/foo/foo_e2e_test.go)
|
||||
# one existing package
|
||||
go test -tags=e2e ./local/foo -count=1 -v -timeout 15m -parallel 1
|
||||
```
|
||||
|
||||
From the repository root: `make -C e2e e2e-local`. From `e2e/`: `make e2e-local`.
|
||||
|
||||
## Minimal skeleton
|
||||
|
||||
```go
|
||||
//go:build e2e
|
||||
|
||||
package local_debug_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
"github.com/azerothcore/AzerothGhost/e2e/e2eharness"
|
||||
)
|
||||
|
||||
func TestLocal_Scratch(t *testing.T) {
|
||||
meta.Begin(t, meta.TestMeta{
|
||||
Tags: []string{"local", "short"},
|
||||
Runtime: "short",
|
||||
Category: "local",
|
||||
})
|
||||
bot := e2eharness.NewSolo(t, e2eharness.ScenarioOpts{
|
||||
Prefix: "Loc",
|
||||
Class: e2eharness.ClassWarrior,
|
||||
Level: 80,
|
||||
})
|
||||
bot.TeleportPad(t, e2eharness.PackagePad(t))
|
||||
// … drive and assert …
|
||||
t.Logf("PASS local scratch")
|
||||
}
|
||||
```
|
||||
|
||||
Authoring rules: AzerothGhost `e2e/LLM_GUIDE.md`. When to keep e2e long-term: `.agents/docs/e2e-policy.md`.
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
"github.com/azerothcore/AzerothGhost/e2e/e2eharness"
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
)
|
||||
|
||||
// SMOKE-07 first: fresh-account create (run early — late runs saw flaky auth EOF
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
"github.com/azerothcore/AzerothGhost/e2e/e2eharness"
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
)
|
||||
|
||||
// Battle Shout ranks (player-cast, cancelable). Do not use GM .aura / 45614 Blending In
|
||||
|
||||
@@ -8,9 +8,9 @@ import (
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
"github.com/azerothcore/AzerothGhost/client"
|
||||
"github.com/azerothcore/AzerothGhost/e2e/e2eharness"
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
"github.com/azerothcore/AzerothGhost/e2e/e2eharness"
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
)
|
||||
|
||||
const spellSummonImp = 688
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
"github.com/azerothcore/AzerothGhost/e2e/e2eharness"
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
)
|
||||
|
||||
// pullDummy is a high-HP training dummy for kill/engage-without-target oracles.
|
||||
|
||||
@@ -8,32 +8,56 @@ import (
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
"github.com/azerothcore/AzerothGhost/e2e/e2eharness"
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
)
|
||||
|
||||
// VEH-* : EnterVehicle / ExitVehicle / IsOnVehicle via Stormwind Steed on PackagePad.
|
||||
// VEH-* : EnterVehicle / ExitVehicle / IsOnVehicle via Stormwind Steed.
|
||||
// Armistice (64373) is required by creature_template vehicle conditions.
|
||||
// spell_area only keeps that aura on the Argent Tournament grounds; PackagePad
|
||||
// (Outland) applies it then strips it, and VehicleAI ejects the rider.
|
||||
|
||||
// spellArmistice (64373) is required by creature_template vehicle conditions
|
||||
// on Stormwind Steed 33217. VehicleAI/SmartAI ExitVehicle the rider without it
|
||||
// (conditions.comment: "Vehicle Stormwind Steed requires aura Armistice").
|
||||
const spellArmistice uint32 = 64373
|
||||
|
||||
func spawnAndBoardSteed(t *testing.T, bot *e2eharness.ScenarioBot) (vehGUID, boarded uint64) {
|
||||
func placeAtArgentTournament(t *testing.T, bots ...*e2eharness.ScenarioBot) {
|
||||
t.Helper()
|
||||
bot.ApplyAura(t, spellArmistice)
|
||||
if !bot.HasAura(spellArmistice) {
|
||||
e2eharness.Preconditionf(t, "Armistice %d not on player (steed vehicle condition)", spellArmistice)
|
||||
for i, bot := range bots {
|
||||
if i == 0 {
|
||||
bot.TeleNamed(t, "ArgentTournament")
|
||||
continue
|
||||
}
|
||||
x, y, z, m := bots[0].Pos()
|
||||
bot.Teleport(t, x+1.5*float32(i), y, z, m)
|
||||
}
|
||||
vehGUID = bot.Spawn(t, e2eharness.CreatureStormwindSteed, 15*time.Second)
|
||||
}
|
||||
|
||||
func ensureArmistice(t *testing.T, bot *e2eharness.ScenarioBot) {
|
||||
t.Helper()
|
||||
// spell_area autocast only. Do not GM-apply: that would hide an area regression.
|
||||
deadline := time.Now().Add(8 * time.Second)
|
||||
for time.Now().Before(deadline) {
|
||||
if bot.HasAura(spellArmistice) {
|
||||
return
|
||||
}
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
}
|
||||
e2eharness.Preconditionf(t, "Armistice %d missing after Argent Tournament enter (spell_area)", spellArmistice)
|
||||
}
|
||||
|
||||
func spawnAndBoardSteed(t *testing.T, bot *e2eharness.ScenarioBot) uint64 {
|
||||
t.Helper()
|
||||
ensureArmistice(t, bot)
|
||||
vehGUID := bot.Spawn(t, e2eharness.CreatureStormwindSteed, 15*time.Second)
|
||||
if vehGUID == 0 {
|
||||
e2eharness.Preconditionf(t, "Stormwind Steed spawn returned guid 0")
|
||||
}
|
||||
boarded = bot.EnterVehicle(t, vehGUID, 12*time.Second)
|
||||
// Re-check immediately before click: spell_area can strip a stale apply.
|
||||
ensureArmistice(t, bot)
|
||||
bot.EnterVehicle(t, vehGUID, 12*time.Second)
|
||||
if !bot.IsOnVehicle() {
|
||||
e2eharness.Preconditionf(t, "not on steed 0x%X after enter (charm=0x%X)", vehGUID, bot.World.PlayerCharmGUID())
|
||||
}
|
||||
return vehGUID, boarded
|
||||
return vehGUID
|
||||
}
|
||||
|
||||
// VEH-01: two bots at the pad; one boards a Stormwind Steed.
|
||||
@@ -41,9 +65,8 @@ func TestVehicles_MultiBotColocated(t *testing.T) {
|
||||
meta.Begin(t, meta.TestMeta{Tags: []string{"short", "combat", "multi_bot"}, Runtime: "short", Category: "combat/vehicles"})
|
||||
|
||||
bots := e2eharness.NewScenario(t, e2eharness.ScenarioOpts{Prefix: "VehCol", Count: 2, Level: 80})
|
||||
pad := e2eharness.PackagePad(t)
|
||||
e2eharness.TeleportAllPad(t, bots, pad)
|
||||
vehGUID, _ := spawnAndBoardSteed(t, bots[0])
|
||||
placeAtArgentTournament(t, bots...)
|
||||
vehGUID := spawnAndBoardSteed(t, bots[0])
|
||||
bots[1].AssertWorldAlive(t)
|
||||
t.Logf("PASS vehicle multi-bot colocation boarded=0x%X", vehGUID)
|
||||
}
|
||||
@@ -53,10 +76,10 @@ func TestVehicles_RelogAfterTeleBaseline(t *testing.T) {
|
||||
meta.Begin(t, meta.TestMeta{Tags: []string{"short", "combat", "protocol"}, Runtime: "short", Category: "combat/vehicles"})
|
||||
|
||||
bot := e2eharness.NewSolo(t, e2eharness.ScenarioOpts{Prefix: "VehRl", Level: 80})
|
||||
bot.TeleportPad(t, e2eharness.PackagePad(t))
|
||||
placeAtArgentTournament(t, bot)
|
||||
bot.Save(t)
|
||||
bot.Relog(t)
|
||||
vehGUID, _ := spawnAndBoardSteed(t, bot)
|
||||
vehGUID := spawnAndBoardSteed(t, bot)
|
||||
t.Logf("PASS relog then board steed 0x%X", vehGUID)
|
||||
}
|
||||
|
||||
@@ -66,8 +89,8 @@ func TestVehicles_HardDisconnectWorldAlive(t *testing.T) {
|
||||
|
||||
probe := e2eharness.NewSolo(t, e2eharness.ScenarioOpts{Prefix: "VehPr", Level: 10})
|
||||
vic := e2eharness.NewSolo(t, e2eharness.ScenarioOpts{Prefix: "VehVc", Level: 80})
|
||||
vic.TeleportPad(t, e2eharness.PackagePad(t))
|
||||
vehGUID, _ := spawnAndBoardSteed(t, vic)
|
||||
placeAtArgentTournament(t, vic)
|
||||
vehGUID := spawnAndBoardSteed(t, vic)
|
||||
e2eharness.HardDisconnectAndProbe(t, vic, probe, 0)
|
||||
t.Logf("PASS passenger hard-drop world alive steed=0x%X", vehGUID)
|
||||
}
|
||||
@@ -77,11 +100,11 @@ func TestVehicles_EnterExitStormwindSteed(t *testing.T) {
|
||||
meta.Begin(t, meta.TestMeta{Tags: []string{"short", "combat", "serial"}, Runtime: "short", Category: "combat/vehicles"})
|
||||
|
||||
bot := e2eharness.NewSolo(t, e2eharness.ScenarioOpts{Prefix: "VehEn", Level: 80})
|
||||
bot.TeleportPad(t, e2eharness.PackagePad(t))
|
||||
placeAtArgentTournament(t, bot)
|
||||
if bot.IsOnVehicle() {
|
||||
e2eharness.Preconditionf(t, "already on vehicle before enter")
|
||||
}
|
||||
vehGUID, _ := spawnAndBoardSteed(t, bot)
|
||||
vehGUID := spawnAndBoardSteed(t, bot)
|
||||
bot.ExitVehicle(t, 12*time.Second)
|
||||
if bot.IsOnVehicle() {
|
||||
e2eharness.Assertf(t, "still IsOnVehicle after ExitVehicle (0x%X)", bot.VehicleGUID())
|
||||
@@ -89,5 +112,3 @@ func TestVehicles_EnterExitStormwindSteed(t *testing.T) {
|
||||
bot.AssertWorldAlive(t)
|
||||
t.Logf("PASS EnterVehicle/ExitVehicle Stormwind Steed 0x%X", vehGUID)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ import (
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
"github.com/azerothcore/AzerothGhost/e2e/e2eharness"
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
)
|
||||
|
||||
// GUILD-01: charter buy + full turn-in via harness CreateGuildViaCharter (SetupGuildLeader).
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
"github.com/azerothcore/AzerothGhost/e2e/e2eharness"
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
)
|
||||
|
||||
// BIND-* : instance party baselines + ritual summon (3 roles) + #10708.
|
||||
@@ -248,5 +248,3 @@ func TestBind_CharacterInstanceAfterEnter(t *testing.T) {
|
||||
bot.AssertWorldAlive(t)
|
||||
t.Logf("PASS character_instance rows=%d map=%d", n, m)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -125,11 +125,24 @@ func TestAC_26363_TimmyEmergesAfterSquareCleared(t *testing.T) {
|
||||
// Center of the 15 relevant Scarlet spawns in Crusaders' Square. The 55-yard
|
||||
// observation radius excludes other Scarlet spawns with the same entries.
|
||||
bot.Teleport(t, 3660, -3180, 127, stratholmeMap)
|
||||
bot.CombatReady(t)
|
||||
triggers := waitForTimmyActivationSet(t, bot, 20*time.Second)
|
||||
if len(triggers) != 15 {
|
||||
e2eharness.Preconditionf(t, "loaded Timmy activation area has %d relevant Scarlets, want 15", len(triggers))
|
||||
}
|
||||
bot.CombatReady(t)
|
||||
// Timmy's emerge tick can fire before this client's cache has the Square
|
||||
// pack (same SHA on ephemeral CI flips pass / "already present"). One
|
||||
// kill+.respawn after the pack is visible resets his SAI.
|
||||
if leftover := bot.FindUnit(npcTimmyTheCruel, 100); leftover != 0 {
|
||||
t.Logf("Timmy 0x%X in cache with Square loaded, killing + .respawn", leftover)
|
||||
bot.DamageKill(t, []uint64{leftover}, 10_000_000, 10*time.Second)
|
||||
bot.GM(t, ".respawn")
|
||||
bot.FlushWorld(t)
|
||||
triggers = waitForTimmyActivationSet(t, bot, 20*time.Second)
|
||||
if len(triggers) != 15 {
|
||||
e2eharness.Preconditionf(t, "after reset, activation area has %d relevant Scarlets, want 15", len(triggers))
|
||||
}
|
||||
}
|
||||
if timmy := bot.FindUnit(npcTimmyTheCruel, 100); timmy != 0 {
|
||||
e2eharness.ConfirmedBugf(t, 26363, "Timmy was already present as 0x%X before the Scarlet activation area was cleared", timmy)
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
"github.com/azerothcore/AzerothGhost/e2e/e2eharness"
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
)
|
||||
|
||||
// OPEN(e2e): re-enable when AC#26266 is fixed — Charge near Kologarn must not drop below bridge Z.
|
||||
@@ -75,6 +75,7 @@ func TestAC_27095_FreyaAlliesSpawnRateReduction(t *testing.T) {
|
||||
Prefix: "Freya",
|
||||
Level: 80,
|
||||
})
|
||||
// Stay GM through the raid enter (.go xyz onto 603 is ignored after .gm off).
|
||||
|
||||
const (
|
||||
npcFreya10 = uint32(32906)
|
||||
@@ -100,16 +101,39 @@ func TestAC_27095_FreyaAlliesSpawnRateReduction(t *testing.T) {
|
||||
return "Unknown"
|
||||
}
|
||||
|
||||
bot.TeleNamed(t, "Freya")
|
||||
// Raid interior pad (game_tele BossFreya). .go xyz is reliable; a missing
|
||||
// custom "Freya" name hangs TeleNamed for 60s.
|
||||
bot.Teleport(t, 2326.82, -48.131, 424.963, e2eharness.MapUlduar)
|
||||
if _, _, _, m := bot.Pos(); m != e2eharness.MapUlduar {
|
||||
e2eharness.Preconditionf(t, "not in Ulduar after Freya pad tele map=%d", m)
|
||||
}
|
||||
bot.GoCreatureID(t, npcFreya10)
|
||||
// Now drop GM. FlushWorld/.gps beside Freya can evade her out of cache,
|
||||
// so re-acquire a living GUID before Engage/FaceUnit.
|
||||
bot.CombatReady(t)
|
||||
|
||||
freyaGUID := bot.WaitUnitAny(t, 30*time.Second, npcFreya10, npcFreya25)
|
||||
// Evade can leave a 0 HP object in cache. Re-poll until we have a living
|
||||
// Freya, not only when the GUID disappears.
|
||||
var freyaGUID uint64
|
||||
deadline := time.Now().Add(30 * time.Second)
|
||||
for {
|
||||
freyaGUID = bot.WaitUnitAny(t, 10*time.Second, npcFreya10, npcFreya25)
|
||||
if hp, maxHP := bot.UnitHP(freyaGUID); maxHP > 0 && hp > 0 {
|
||||
if bot.World.GetObject(freyaGUID) != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
if !time.Now().Before(deadline) {
|
||||
e2eharness.Preconditionf(t, "no living Freya in cache after GoCreatureID (last=0x%X)", freyaGUID)
|
||||
}
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
}
|
||||
bot.Engage(t, freyaGUID, 15*time.Second)
|
||||
|
||||
tr := e2eharness.NewSpawnSetTracker(allyEntries, 3*time.Second)
|
||||
tr.KindOf = func(entry uint32) string { return label(entry) }
|
||||
sets := tr.WaitSets(t, bot.World, 2, 4*time.Minute)
|
||||
// Waves are ~60s apart. 90s covers two waves; 4m just delayed a miss.
|
||||
sets := tr.WaitSets(t, bot.World, 2, 90*time.Second)
|
||||
t.Logf("Set1=%s units=%d Set2=%s units=%d gap=%s",
|
||||
sets[0].Kind, len(sets[0].Guids),
|
||||
sets[1].Kind, len(sets[1].Guids),
|
||||
@@ -118,7 +142,7 @@ func TestAC_27095_FreyaAlliesSpawnRateReduction(t *testing.T) {
|
||||
// Detonating Lashers explode on death — if Set1 is Lashers, wait for Set3
|
||||
// and kill Set2 (still: older set while a newer set is up).
|
||||
if sets[0].Kind == "Lashers" {
|
||||
sets = tr.WaitSets(t, bot.World, 3, 4*time.Minute)
|
||||
sets = tr.WaitSets(t, bot.World, 3, 150*time.Second)
|
||||
}
|
||||
|
||||
var older, newer e2eharness.SpawnSet
|
||||
@@ -131,7 +155,6 @@ func TestAC_27095_FreyaAlliesSpawnRateReduction(t *testing.T) {
|
||||
e2eharness.Preconditionf(t, "cannot find a non-Lasher older set to kill without collateral explosions")
|
||||
}
|
||||
|
||||
time.Sleep(2 * time.Second)
|
||||
tr.Poll(bot.World, time.Now())
|
||||
|
||||
var olderLive []uint64
|
||||
@@ -176,9 +199,9 @@ func TestAC_27095_FreyaAlliesSpawnRateReduction(t *testing.T) {
|
||||
for _, s := range bot.UnitsByEntry(120, allyEntries...) {
|
||||
knownAtKill[s.GUID] = struct{}{}
|
||||
}
|
||||
fresh := bot.WaitNewUnits(t, knownAtKill, allyEntries, 90*time.Second)
|
||||
fresh := bot.WaitNewUnits(t, knownAtKill, allyEntries, 75*time.Second)
|
||||
if len(fresh) == 0 {
|
||||
e2eharness.Preconditionf(t, "no new ally set spawned within 90s after older-set kill")
|
||||
e2eharness.Preconditionf(t, "no new ally set spawned within 75s after older-set kill")
|
||||
}
|
||||
nextT := time.Now()
|
||||
fromNewer := nextT.Sub(newer.SpawnT)
|
||||
@@ -245,7 +268,7 @@ func TestUlduar_MultiBotLoginNearBossPad(t *testing.T) {
|
||||
Level: 80,
|
||||
})
|
||||
for _, b := range bots {
|
||||
b.TeleNamed(t, "Freya")
|
||||
b.Teleport(t, 2326.82, -48.131, 424.963, e2eharness.MapUlduar)
|
||||
}
|
||||
_, _, _, m0 := bots[0].Pos()
|
||||
_, _, _, m1 := bots[1].Pos()
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
"github.com/azerothcore/AzerothGhost/e2e/e2eharness"
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
)
|
||||
|
||||
// EQUIP-01: add+inventory oracle (EquipEntry is EQUIP-04).
|
||||
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
"github.com/azerothcore/AzerothGhost/e2e/e2eharness"
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
)
|
||||
|
||||
// SESS-01: position readable after login (seed of inventory/pos load).
|
||||
|
||||
@@ -9,8 +9,8 @@ import (
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
"github.com/azerothcore/AzerothGhost/e2e/e2eharness"
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
)
|
||||
|
||||
// TELE-01: cross-map teleport (EK → Northrend).
|
||||
|
||||
@@ -9,8 +9,8 @@ import (
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
"github.com/azerothcore/AzerothGhost/e2e/e2eharness"
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
)
|
||||
|
||||
// OPEN(e2e): replace this package with a real escort quest fixture (start → follow →
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
"github.com/azerothcore/AzerothGhost/e2e/e2eharness"
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
)
|
||||
|
||||
// QLIFE-03 / #26549: STAY_ALIVE quest fails on death.
|
||||
|
||||
@@ -8,9 +8,9 @@ import (
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
"github.com/azerothcore/AzerothGhost/client"
|
||||
"github.com/azerothcore/AzerothGhost/e2e/e2eharness"
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
)
|
||||
|
||||
// GRP-01: FormParty → both InGroup, leader flag.
|
||||
|
||||
@@ -8,9 +8,9 @@ import (
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
"github.com/azerothcore/AzerothGhost/client"
|
||||
"github.com/azerothcore/AzerothGhost/e2e/e2eharness"
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
)
|
||||
|
||||
// LOOT-01: Need vs Greed on a guaranteed Uncommon drop (Crimson Templar).
|
||||
|
||||
@@ -9,9 +9,9 @@ import (
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
"github.com/azerothcore/AzerothGhost/client"
|
||||
"github.com/azerothcore/AzerothGhost/e2e/e2eharness"
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
)
|
||||
|
||||
// Cheap stackable trade bait (Linen Cloth).
|
||||
@@ -108,6 +108,15 @@ func waitInvAtLeast(t *testing.T, bot *e2eharness.ScenarioBot, entry uint32, lea
|
||||
return n
|
||||
}
|
||||
|
||||
func waitInvEqual(t *testing.T, bot *e2eharness.ScenarioBot, entry uint32, want int, timeout time.Duration) int {
|
||||
t.Helper()
|
||||
n := waitInv(t, bot, entry, func(got int) bool { return got == want }, timeout)
|
||||
if n != want {
|
||||
e2eharness.Assertf(t, "inventory entry=%d count=%d want=%d", entry, n, want)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// Spec 1 — Item + gold dual-accept.
|
||||
func TestTrade_ItemGoldDualAcceptInventories(t *testing.T) {
|
||||
meta.Begin(t, meta.TestMeta{Tags: []string{"short", "trade", "multi_bot"}, Runtime: "short", Category: "social/trade"})
|
||||
@@ -233,24 +242,19 @@ func TestTrade_StackableMerge(t *testing.T) {
|
||||
// After accept: totals conserved and B gains.
|
||||
bag, slot := a.AddItemWait(t, itemLinenCloth, 5)
|
||||
b.AddItemWait(t, itemLinenCloth, 3)
|
||||
a0 := a.InventoryCount(t, itemLinenCloth)
|
||||
b0 := b.InventoryCount(t, itemLinenCloth)
|
||||
if a0 < 5 || b0 < 3 {
|
||||
e2eharness.Preconditionf(t, "seed failed a=%d b=%d", a0, b0)
|
||||
}
|
||||
// Same oracle as the dual-accept test: client push can land before CharDB.
|
||||
a0 := waitInvAtLeast(t, a, itemLinenCloth, 5, 10*time.Second)
|
||||
b0 := waitInvAtLeast(t, b, itemLinenCloth, 3, 10*time.Second)
|
||||
|
||||
e2eharness.OpenTrade(t, a, b)
|
||||
a.SetTradeItem(t, 0, bag, slot)
|
||||
e2eharness.CompleteTrade(t, a, b)
|
||||
|
||||
a1 := a.InventoryCount(t, itemLinenCloth)
|
||||
b1 := b.InventoryCount(t, itemLinenCloth)
|
||||
a1 := waitInvEqual(t, a, itemLinenCloth, a0-5, 10*time.Second)
|
||||
b1 := waitInvEqual(t, b, itemLinenCloth, b0+5, 10*time.Second)
|
||||
if a1+b1 != a0+b0 {
|
||||
e2eharness.Assertf(t, "linen not conserved %d+%d → %d+%d", a0, b0, a1, b1)
|
||||
}
|
||||
if b1 <= b0 {
|
||||
e2eharness.Assertf(t, "B did not gain stack %d→%d", b0, b1)
|
||||
}
|
||||
t.Logf("PASS stackable merge/conserve a %d→%d b %d→%d", a0, a1, b0, b1)
|
||||
}
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
"github.com/azerothcore/AzerothGhost/e2e/e2eharness"
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
)
|
||||
|
||||
// Issue: https://github.com/azerothcore/azerothcore-wotlk/issues/26130
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
"github.com/azerothcore/AzerothGhost/e2e/e2eharness"
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
)
|
||||
|
||||
// CAST-01: live cast pipeline — Charge succeeds on spawned dummy after CombatReady.
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
"github.com/azerothcore/AzerothGhost/e2e/e2eharness"
|
||||
"github.com/azerothcore/azerothcore-wotlk/e2e/internal/meta"
|
||||
)
|
||||
|
||||
// OPEN(e2e): re-enable when AC#26774 is fixed
|
||||
|
||||
Reference in New Issue
Block a user