|
1 | 1 | import { describe, expect, jest, test } from "@jest/globals"; |
2 | 2 | import { existsSync, readFileSync, rmSync, writeFileSync } from "node:fs"; |
3 | 3 | import path from "path"; |
4 | | -import { cli } from "./helpers"; |
| 4 | +import { cli, normalizePaths } from "./helpers"; |
5 | 5 |
|
6 | 6 | describe("cli", () => { |
7 | 7 | test("--version", async () => { |
@@ -129,3 +129,88 @@ describe("install", () => { |
129 | 129 | } |
130 | 130 | }); |
131 | 131 | }); |
| 132 | + |
| 133 | +// `mops update` and `mops outdated` default to caret-bound resolution: stay |
| 134 | +// within `0.x.y` (or `1.x.y`) and never cross majors. Fixture pins: |
| 135 | +// base = "0.14.5" -> caret bumps within 0.14.x; --major jumps past it |
| 136 | +// core = "1.0.0" -> caret stays put (no 1.x.y > 1.0.0); --major jumps to 2.x |
| 137 | +describe("update / outdated bounds", () => { |
| 138 | + jest.setTimeout(120_000); |
| 139 | + |
| 140 | + const cwd = path.join(import.meta.dirname, "install/update-bound"); |
| 141 | + const tomlFile = path.join(cwd, "mops.toml"); |
| 142 | + const original = readFileSync(tomlFile, "utf8"); |
| 143 | + |
| 144 | + const cleanup = () => { |
| 145 | + rmSync(path.join(cwd, "mops.lock"), { force: true }); |
| 146 | + rmSync(path.join(cwd, ".mops"), { recursive: true, force: true }); |
| 147 | + writeFileSync(tomlFile, original); |
| 148 | + }; |
| 149 | + |
| 150 | + const baseVersion = (toml: string) => |
| 151 | + toml.match(/base = "(0\.\d+\.\d+)"/)?.[1]; |
| 152 | + const coreMajor = (toml: string) => |
| 153 | + parseInt(toml.match(/core = "(\d+)\./)?.[1] ?? "0"); |
| 154 | + |
| 155 | + test("mops update stays within the caret bound by default", async () => { |
| 156 | + cleanup(); |
| 157 | + try { |
| 158 | + await cli(["install"], { cwd, env: { CI: undefined } }); |
| 159 | + const result = await cli(["update"], { cwd, env: { CI: undefined } }); |
| 160 | + expect(result.exitCode).toBe(0); |
| 161 | + const after = readFileSync(tomlFile, "utf8"); |
| 162 | + // base (pre-1.0): bumped within 0.14.x (patch bumps allowed) |
| 163 | + expect(baseVersion(after)).toMatch(/^0\.14\./); |
| 164 | + expect(baseVersion(after)).not.toBe("0.14.5"); |
| 165 | + // core (1.x): no 1.x.y > 1.0.0 published, so no bump across majors |
| 166 | + expect(coreMajor(after)).toBe(1); |
| 167 | + } finally { |
| 168 | + cleanup(); |
| 169 | + } |
| 170 | + }); |
| 171 | + |
| 172 | + test("mops update --major crosses the caret bound", async () => { |
| 173 | + cleanup(); |
| 174 | + try { |
| 175 | + await cli(["install"], { cwd, env: { CI: undefined } }); |
| 176 | + const result = await cli(["update", "--major"], { |
| 177 | + cwd, |
| 178 | + env: { CI: undefined }, |
| 179 | + }); |
| 180 | + expect(result.exitCode).toBe(0); |
| 181 | + const after = readFileSync(tomlFile, "utf8"); |
| 182 | + // base: jumps past 0.14.x (next minor or major) |
| 183 | + const baseMinor = parseInt(after.match(/base = "0\.(\d+)\./)?.[1] ?? "0"); |
| 184 | + expect(baseMinor).toBeGreaterThanOrEqual(15); |
| 185 | + // core: jumps to 2.x or later |
| 186 | + expect(coreMajor(after)).toBeGreaterThanOrEqual(2); |
| 187 | + } finally { |
| 188 | + cleanup(); |
| 189 | + } |
| 190 | + }); |
| 191 | + |
| 192 | + test("mops outdated honors --major flag", async () => { |
| 193 | + cleanup(); |
| 194 | + try { |
| 195 | + await cli(["install"], { cwd, env: { CI: undefined } }); |
| 196 | + const caret = normalizePaths( |
| 197 | + (await cli(["outdated"], { cwd, env: { CI: undefined } })).stdout, |
| 198 | + ); |
| 199 | + const major = normalizePaths( |
| 200 | + (await cli(["outdated", "--major"], { cwd, env: { CI: undefined } })) |
| 201 | + .stdout, |
| 202 | + ); |
| 203 | + // caret-bound: base bumps within 0.14.x; core (if reported) stays in 1.x |
| 204 | + expect(caret).toMatch(/base 0\.14\.5 -> 0\.14\./); |
| 205 | + const caretCore = caret.match(/core 1\.0\.0 -> (\d+)\./)?.[1]; |
| 206 | + if (caretCore) { |
| 207 | + expect(parseInt(caretCore)).toBe(1); |
| 208 | + } |
| 209 | + // --major: both bump across their major bounds |
| 210 | + expect(major).toMatch(/base 0\.14\.5 -> 0\.(1[5-9]|[2-9]\d)/); |
| 211 | + expect(major).toMatch(/core 1\.0\.0 -> [2-9]/); |
| 212 | + } finally { |
| 213 | + cleanup(); |
| 214 | + } |
| 215 | + }); |
| 216 | +}); |
0 commit comments