|
| 1 | +import { readFileSync } from 'fs' |
| 2 | +import { createRequire } from 'module' |
| 3 | +import { join } from 'path' |
| 4 | + |
| 5 | +import chai from 'chai' |
| 6 | + |
| 7 | +const { expect } = chai |
| 8 | + |
| 9 | +type CommitModule = { |
| 10 | + getAddMessage: (changeset: { summary: string }, options: unknown) => string |
| 11 | + getVersionMessage: (releasePlan: { releases: unknown[] }, options: unknown) => string |
| 12 | +} |
| 13 | + |
| 14 | +describe('changesets commit message', () => { |
| 15 | + const config = JSON.parse(readFileSync(join(process.cwd(), '.changeset', 'config.json'), 'utf-8')) as { |
| 16 | + commit: unknown |
| 17 | + } |
| 18 | + |
| 19 | + // createRequire works whether mocha loads this spec as CommonJS or as an ES |
| 20 | + // module, which `require` itself does not. |
| 21 | + const loadFromRepo = createRequire(join(process.cwd(), 'index.js')) |
| 22 | + |
| 23 | + // Changesets resolves the specifier in the `commit` tuple as if it were |
| 24 | + // imported from `<repo>/.changeset/x.mjs`, so that is the base used here too. |
| 25 | + const commitModule = (): CommitModule => { |
| 26 | + expect(config.commit, '`commit` in .changeset/config.json must be a [module, options] tuple').to.be.an('array') |
| 27 | + const specifier = (config.commit as unknown[])[0] |
| 28 | + expect(specifier, 'that tuple must name a module').to.be.a('string') |
| 29 | + |
| 30 | + return loadFromRepo(join(process.cwd(), '.changeset', specifier as string)) as CommitModule |
| 31 | + } |
| 32 | + |
| 33 | + // The options Changesets actually passes to the module, so a change to them |
| 34 | + // (say `skipCI: true`) cannot quietly put `[skip ci]` back on the version |
| 35 | + // commit without failing these assertions. |
| 36 | + const configuredOptions = (config.commit as unknown[])[1] ?? null |
| 37 | + |
| 38 | + const releasePlan = { |
| 39 | + releases: [ |
| 40 | + { name: 'nostream', type: 'minor', oldVersion: '3.0.0', newVersion: '3.1.0' }, |
| 41 | + { name: 'nostream-extra', type: 'none', oldVersion: '1.0.0', newVersion: '1.0.0' }, |
| 42 | + ], |
| 43 | + } |
| 44 | + |
| 45 | + // The stock message is `RELEASING: Releasing N package(s)`, which commitlint |
| 46 | + // rejects for type-case and type-enum. |
| 47 | + it('writes a conventional subject', () => { |
| 48 | + expect(commitModule().getVersionMessage(releasePlan, configuredOptions)).to.equal('chore: release nostream@3.1.0') |
| 49 | + }) |
| 50 | + |
| 51 | + // `[skip ci]` makes GitHub skip both push and pull_request runs for the |
| 52 | + // commit, which is why the version PR's required checks never reported. |
| 53 | + it('writes no [skip ci]', () => { |
| 54 | + expect(commitModule().getVersionMessage(releasePlan, configuredOptions)).not.to.include('skip ci') |
| 55 | + }) |
| 56 | + |
| 57 | + it('names only the packages that are actually released', () => { |
| 58 | + expect(commitModule().getVersionMessage(releasePlan, configuredOptions)).not.to.include('nostream-extra') |
| 59 | + }) |
| 60 | + |
| 61 | + it('still honours skipCI when it is asked for', () => { |
| 62 | + expect(commitModule().getVersionMessage(releasePlan, { skipCI: true })).to.include('[skip ci]') |
| 63 | + }) |
| 64 | + |
| 65 | + it('keeps changeset add conventional', () => { |
| 66 | + expect(commitModule().getAddMessage({ summary: 'a summary' }, { skipCI: false })).to.equal( |
| 67 | + 'docs(changeset): a summary', |
| 68 | + ) |
| 69 | + }) |
| 70 | +}) |
0 commit comments