diff --git a/flake.nix b/flake.nix index bef62ee..a39fdce 100644 --- a/flake.nix +++ b/flake.nix @@ -20,7 +20,7 @@ checks.x86_64-linux.default = bp.outputs.legacyPackages.x86_64-linux.buildYarnPackage { src = ./.; - yarnBuildMore = "yarn test"; + yarnBuildMore = "yarn build; yarn test"; }; }; } diff --git a/src/index.spec.ts b/src/index.spec.ts index d53d8d3..6b639db 100644 --- a/src/index.spec.ts +++ b/src/index.spec.ts @@ -1,7 +1,7 @@ import { describe, expect, it } from 'vitest'; import fc from 'fast-check'; import { - /*afterFirstWord, beforeFirstWord, */ afterFirst, afterLast, endsWith, ltrim, rtrim, trim, startsWith, + /*afterFirstWord, beforeFirstWord, */ afterFirst, afterLast, endsWith, ltrim, rtrim, trim, startsWith, beforeFirst, } from './index'; describe('strings', () => { @@ -53,6 +53,16 @@ describe('strings', () => { expect(afterLast('&', 'foo bar bat')).toBe('foo bar bat'); }) }) + + describe('beforeFirst', () => { + it('removes everything after the first needle when possible', () => { + expect(beforeFirst(' ', 'foo bar bat')).toBe('foo'); + }) + + it('removes everythin when needle is not present', () => { + expect(beforeFirst('&', 'foo bar bat')).toBe(''); + }) + }) // describe('afterFirstWord', () => { // it('removes the first word', () => { // fc.assert(fc.property(fc.string(), (str) => { @@ -67,4 +77,79 @@ describe('strings', () => { // })); // }); // }); + describe('ltrim', () => { + it('returns input when cutset is empty', () => { + expect(ltrim('', 'foo')).toBe('foo'); + }); + it('returns empty when input is empty', () => { + expect(ltrim('foo', '')).toBe(''); + }); + it('can be curried', () => { + expect(ltrim('foo', '')).toBe(ltrim('foo')('')); + expect(ltrim(' ', ' foo')).toBe(ltrim(' ')(' foo')); + }); + it('trims cutset', () => { + fc.assert(fc.property(fc.string(), fc.string(), (cutset, str) => { + const got = ltrim(cutset, str); + + if (cutset === '') { + expect(got).toBe(str); + } else if (str === '') { + expect(got).toBe(''); + } else { + if (got === '') { + for (const char of str) { + expect(cutset).contains(char); + } + } + + for (const char of cutset) { + expect(startsWith(char, got)).toBe(false); + } + } + })); + }); + }); + + describe('rtrim', () => { + it('returns input when cutset is empty', () => { + expect(rtrim('', 'foo')).toBe('foo'); + }); + it('returns empty when input is empty', () => { + expect(rtrim('foo', '')).toBe(''); + }); + it('can be curried', () => { + expect(rtrim('foo', '')).toBe(rtrim('foo')('')); + expect(rtrim(' ', ' foo')).toBe(rtrim(' ')(' foo')); + }); + it('trims cutset', () => { + fc.assert(fc.property(fc.string(), fc.string(), (cutset, str) => { + const got = rtrim(cutset, str); + + if (cutset === '') { + expect(got).toBe(str); + } else if (str === '') { + expect(got).toBe(''); + } else { + if (got === '') { + for (const char of str) { + expect(cutset).contains(char); + } + } + + for (const char of cutset) { + expect(endsWith(char, got)).toBe(false); + } + } + })); + }); + }); + + describe('trim', () => { + it("composes 'ltrim' and 'rtrim'", function() { + fc.assert(fc.property(fc.string(), fc.string(), (cutset, str) => { + expect(trim(cutset, str)).toBe(ltrim(cutset, rtrim(cutset, str))); + })); + }); + }) }); \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index fa620a9..ca43725 100644 --- a/src/index.ts +++ b/src/index.ts @@ -18,17 +18,12 @@ export const afterLast = curry( (separator: string, str: string) => str.substring(str.lastIndexOf(separator) + 1, str.length), ); -// export const beforeFirst = curry( -// /** -// * -// * @param {String} separator -// * @param {String} str -// * @returns {String} -// */ -// (separator, str) => str.substring(0, str.indexOf(separator)), -// ); +export const beforeFirst = curry( + (separator: string, str: string) => str.substring(0, str.indexOf(separator)), +); -// export const beforeFirstWord = beforeFirst(' '); +// @todo Test +export const beforeFirstWord = beforeFirst(' '); // /** // * @param {String} str