Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: fix types, remove applyMethod function and update tests #83

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
23 changes: 0 additions & 23 deletions src/config/applyMethods.ts

This file was deleted.

7 changes: 3 additions & 4 deletions src/config/getConfig.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import parseSelector from './parseSelector';
import { ElementPassArg } from '../parser/types';
import { Config, RawConfig } from './types';
import { applyMethods } from './applyMethods';
import { type ElementPassArg } from '../parser/types';
import { type Config, type RawConfig } from './types';

function getConfig(
{ $, el }: ElementPassArg,
Expand Down Expand Up @@ -51,7 +50,7 @@ function getConfig<Initial = unknown>(
};
}

return applyMethods(config);
return config;
}

export default getConfig;
47 changes: 38 additions & 9 deletions src/config/parseSelector.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Selector, RawConfig } from './types';
import { type Selector, type RawConfig, type Method } from './types';

function parseSelector<Initial = unknown>(
selector: Selector
Expand All @@ -14,7 +14,43 @@ function parseSelector<Initial = unknown>(
if (selector.includes('|')) {
[$selector, ...methods] = selector.split('|').map((key) => key.trim());

methods = methods.map((p: string) => p.trim());
if (methods.length > 0) {
const validMethods = [
'boolean',
'float',
'number',
'length',
'lowercase',
'uppercase',
'email',
'url'
];

const acceptedMethods = methods.filter((method: string) =>
validMethods.includes(method)
) as Method[];

const type = methods.includes('array') ? 'array' : config.type;
const html = methods.includes('html') ? true : config.html;
const exist = methods.includes('exist') ? true : config.exist;

let trim = config.trim;

if (methods.includes('trim')) {
trim = true;
} else if (methods.includes('non-trim')) {
trim = false;
}

if (type) config.type = type;
if (html) config.html = html;
if (exist) config.exist = exist;
if (typeof trim === 'boolean') config.trim = trim;

if (acceptedMethods.length > 0) {
config.methods = acceptedMethods;
}
}
}

if ($selector === undefined) {
Expand All @@ -34,13 +70,6 @@ function parseSelector<Initial = unknown>(

if (attr) config.attr = attr;

if (methods?.length) {
if (methods.includes('array')) {
config.type = 'array';
}
config.methods = methods.filter((i) => i !== 'array');
}

return config;
}

Expand Down
16 changes: 13 additions & 3 deletions src/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,30 @@ export type ElementFilterFunction = (
$: CheerioAPI
) => boolean;

export type ConfigTypeValues = 'number' | 'float' | 'boolean' | 'array';
export type Method =
| 'boolean'
| 'number'
| 'float'
| 'length'
| 'lowercase'
| 'uppercase'
| 'email'
| 'url';

export type Types = 'number' | 'float' | 'boolean' | 'array';

export interface RawConfig<Initial = unknown> {
selector?: Selector;
html?: boolean;
attr?: string | string[];
type?: ConfigTypeValues;
type?: Types;
trim?: boolean;
exist?: boolean;
rootScope?: boolean;
elementFilter?: ElementFilterFunction;
initial?: Initial;
fill?: any;
methods?: string[];
methods?: Method[];
regex?: RegexConfig;
transform?: TransformFunction<Initial>;
arrayTransform?: TransformFunction<any[]>;
Expand Down
4 changes: 1 addition & 3 deletions src/parser/getValue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ function getValue<Initial = unknown>(
const { schema } = rest;
const elemExists = element.length > 0;

if (exist || config.methods?.includes('exist')) {
return elemExists;
}
if (exist) return elemExists;

if (condition && !condition($(el))) {
return rest.initial ?? null;
Expand Down
2 changes: 1 addition & 1 deletion src/parser/methods/boolean.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
const boolean = (val: any): boolean => Boolean(val);
const boolean = (val: any) => Boolean(val);

export default boolean;
2 changes: 1 addition & 1 deletion src/parser/methods/email.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import execRegex from '../regex/execRegex';

const email = (val: any): string => execRegex(val, 'email');
const email = (val: any) => execRegex(val, 'email');

export default email;
2 changes: 1 addition & 1 deletion src/parser/methods/float.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
const float = (val: string): number => parseFloat(val);
const float = (val: string) => parseFloat(val);

export default float;
2 changes: 1 addition & 1 deletion src/parser/methods/length.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
const length = (val: any): number => val?.length || 0;
const length = (val: any) => val?.length || 0;

export default length;
2 changes: 1 addition & 1 deletion src/parser/methods/lowercase.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
const lowercase = (val: string): string => val.toLowerCase();
const lowercase = (val: string) => val.toLowerCase();

export default lowercase;
2 changes: 1 addition & 1 deletion src/parser/methods/number.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
const number = (val: string): number => parseInt(val);
const number = (val: string) => parseInt(val);

export default number;
2 changes: 1 addition & 1 deletion src/parser/methods/uppercase.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
const uppercase = (val: string): string => val.toUpperCase();
const uppercase = (val: string) => val.toUpperCase();

export default uppercase;
2 changes: 1 addition & 1 deletion src/parser/methods/url.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import execRegex from '../regex/execRegex';

const url = (val: any): string => execRegex(val, 'url');
const url = (val: any) => execRegex(val, 'url');

export default url;
5 changes: 2 additions & 3 deletions src/parser/transformValue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ import { Cheerio, Element } from 'cheerio';
import { RawConfig } from '../config/types';
import Methods from './methods';
import execRegex from './regex/execRegex';
import { Value } from './value';

function transformValue<Initial = unknown>(
value: Value<Initial>,
value: any,
config: RawConfig<Initial>,
element: Cheerio<Element>
) {
Expand All @@ -19,7 +18,7 @@ function transformValue<Initial = unknown>(
if (value) value = value.trim();
}

if (type) {
if (type && type !== 'array') {
methods.push(type);
}

Expand Down
63 changes: 29 additions & 34 deletions tests/getConfig.spec.ts
Original file line number Diff line number Diff line change
@@ -1,49 +1,49 @@
import { describe, it, expect } from 'vitest';

import getConfig from '../src/config/getConfig';
import parseSelector from '../src/config/parseSelector';
import { RawConfig } from '../src/config/types';

describe('getConfig Tests', () => {
it('Case 1: string config: @ attr', () => {
const config = { selector: '@ href' };
it('should return empty selector and "href" attribute when given a string config with "@ attr"', () => {
const config: RawConfig = { selector: '@ href' };
const value = getConfig({}, config);
const expected = { selector: '', attr: 'href' };

expect(value).to.deep.equal(expected);
});

it('Case 2: string config: selector', () => {
const config = { selector: 'a.link' };
it('should return the same selector when given a string config without "@ attr"', () => {
const config: RawConfig = { selector: 'a.link' };
const value = getConfig({}, config);
expect({ selector: 'a.link' }).to.deep.equal(value);
});

it('Case 3: string config: selector @ attr', () => {
const config = { selector: 'a.link @ href' };
it('should return the selector and "href" attribute when given a string config with "selector @ attr"', () => {
const config: RawConfig = { selector: 'a.link @ href' };
const value = getConfig({}, config);
expect({ selector: 'a.link', attr: 'href' }).to.deep.equal(value);
});

it('Case 4: array config: [selector, selector]', () => {
const config = { selector: 'a.link, b.link' };
it('should return the same selector when given an array config with multiple selectors', () => {
const config: RawConfig = { selector: 'a.link, b.link' };
const value = getConfig({}, config);
expect({ selector: 'a.link, b.link' }).to.deep.equal(value);
});

it('Case 5: object config: { selector, attr }', () => {
const config = { selector: 'a.link', attr: 'href' };
it('should return the selector and attribute when given an object config with "selector" and "attr"', () => {
const config: RawConfig = { selector: 'a.link', attr: 'href' };
const value = getConfig({}, config);
expect({ selector: 'a.link', attr: 'href' }).to.deep.equal(value);
});

it('Case 6: object config: { selector @ attr }', () => {
const config = { selector: 'a.link @ href' };
it('should return the selector and attribute when given an object config with "selector @ attr"', () => {
const config: RawConfig = { selector: 'a.link @ href' };
const value = getConfig({}, config);
expect({ selector: 'a.link', attr: 'href' }).to.deep.equal(value);
});

it('Case 7: object config: { selector @ attr | method }', () => {
const config = { selector: 'a.link @ href | url' };
it('should return the selector, attribute, and methods when given an object config with "selector @ attr | method"', () => {
const config: RawConfig = { selector: 'a.link @ href | url' };
const value = getConfig({}, config);
expect({
selector: 'a.link',
Expand All @@ -52,58 +52,53 @@ describe('getConfig Tests', () => {
}).to.deep.equal(value);
});

it('Case 8: object config: { selector @ attr | array* }', () => {
const config = { selector: 'a.link @ href | array' };
it('should return the selector, attribute, and type when given an object config with "selector @ attr | array"', () => {
const config: RawConfig = { selector: 'a.link @ href | array' };
const value = getConfig({}, config);
expect({
selector: 'a.link',
attr: 'href',
type: 'array',
methods: []
type: 'array'
}).to.deep.equal(value);
});

it('Case 9: object config: { selector @ attr | html* }', () => {
const config = { selector: 'a.link @ href | html' };
it('should return the selector, attribute, and html flag when given an object config with "selector @ attr | html"', () => {
const config: RawConfig = { selector: 'a.link @ href | html' };
const value = getConfig({}, config);
expect({
selector: 'a.link',
attr: 'href',
html: true,
methods: ['html']
html: true
}).to.deep.equal(value);
});

it('Case 10: object config: () => ({ selector @ attr | html* })', () => {
const config = {
it('should return the selector, attribute, and html flag when given an object config as a function', () => {
const config: RawConfig = {
selector: 'a.link @ href | html'
};
const value = getConfig({}, config);
const expected = {
selector: 'a.link',
attr: 'href',
html: true,
methods: ['html']
html: true
};

expect(value).to.deep.equal(expected);
});

it('Case 11: object config: () => ({ selector | exist })', () => {
const config = { selector: 'a.link | exist' };
it('should return the selector and exist flag when given an object config as a function', () => {
const config: RawConfig = { selector: 'a.link | exist' };
const value = getConfig({}, config);
expect({
selector: 'a.link',
exist: true,
methods: ['exist']
exist: true
}).to.deep.equal(value);
});

it('MultipleStringSelectors', () => {
it('should return the parsed selectors when given an array of string selectors', () => {
const selectors = ['a.link', 'b.link'];
const result = getConfig({}, selectors);
const expected = selectors.map((s) => parseSelector(s));

const expected = [{ selector: 'a.link' }, { selector: 'b.link' }];
expect(result).to.deep.equal(expected);
});
});
2 changes: 1 addition & 1 deletion tests/getValue.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ describe('getValue Tests', () => {
it('Case 17: { selector, non-exist }', () => {
const el = $('.parent');
const selector = '.non-exist-child';
const value = getValue({ $, el }, { selector, methods: ['exist'] });
const value = getValue({ $, el }, { selector, exist: true });

expect(value).to.deep.equal(false);
});
Expand Down
3 changes: 1 addition & 2 deletions tests/parseSelector.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,7 @@ describe('parseSelector Tests', () => {
const value = parseSelector(selector);
expect({
selector: '.parent div',
type: 'array',
methods: []
type: 'array'
}).to.deep.equal(value);
});

Expand Down
Loading
Loading