Skip to content

Commit

Permalink
feat(n4s): added 'isKeyOf' rule (ealush#771)
Browse files Browse the repository at this point in the history
  • Loading branch information
galezra authored and shani-arnon committed Aug 4, 2022
1 parent 6e63edf commit 8192b5b
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 29 deletions.
58 changes: 29 additions & 29 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
name: 'CodeQL'

on:
push:
branches: [ latest, stable ]
branches: [latest, stable]
pull_request:
# The branches below must be a subset of the branches above
branches: [ latest, vest-4-integration-branch ]
branches: [latest, vest-4-integration-branch]
schedule:
- cron: '29 14 * * 6'

Expand All @@ -32,39 +32,39 @@ jobs:
strategy:
fail-fast: false
matrix:
language: [ 'javascript', 'TypeScript' ]
language: ['javascript', 'TypeScript']
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support

steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Checkout repository
uses: actions/checkout@v2

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main

# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1

# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl

# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language

#- run: |
# make bootstrap
# make release
#- run: |
# make bootstrap
# make release

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
62 changes: 62 additions & 0 deletions packages/n4s/src/rules/__tests__/isKeyOf.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { enforce } from 'enforce';
import { isKeyOf, isNotKeyOf } from 'isKeyOf';

const FRUITES = {
apples: 5,
bananas: 2,
cantelopes: 0,
};

const TOP_GROSSING_MOVIES = {
1976: 'Rocky',
1988: 'Rain Man',
2008: 'The Dark Knight',
};

const DUMMY_KEY = 'key';

describe('Tests isKeyOf rule', () => {
describe('When the key exists in the object', () => {
it('Should return true', () => {
expect(isKeyOf('bananas', FRUITES)).toBe(true);
expect(isKeyOf(1976, TOP_GROSSING_MOVIES)).toBe(true);
});

it('Should return true using enforce', () => {
enforce('bananas').isKeyOf(FRUITES);
enforce(1976).isKeyOf(TOP_GROSSING_MOVIES);
});
});

describe('When the key does not exists in the object', () => {
it('Should return false', () => {
expect(isKeyOf('avocado', FRUITES)).toBe(false);
expect(isKeyOf(1999, TOP_GROSSING_MOVIES)).toBe(false);
});

it.each([undefined, null, false, true, Object, [], '', Function.prototype])(
'Should throw when %s is an object',
v => {
expect(() => enforce(DUMMY_KEY).isKeyOf({ v })).toThrow();
}
);
});
});

describe('Tests isNotKeyOf rule', () => {
describe('When the key does not exists in the object', () => {
it('Should return true', () => {
expect(isNotKeyOf('avocado', FRUITES)).toBe(true);
});

it('Should return true using enforce', () => {
enforce(1999).isNotKeyOf(TOP_GROSSING_MOVIES);
});
});

describe('When the key exists in the object', () => {
it('Should return false', () => {
expect(isNotKeyOf(1976, TOP_GROSSING_MOVIES)).toBe(false);
});
});
});
7 changes: 7 additions & 0 deletions packages/n4s/src/rules/isKeyOf.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import bindNot from 'bindNot';

export function isKeyOf(key: string | symbol | number, obj: any): boolean {
return key in obj;
}

export const isNotKeyOf = bindNot(isKeyOf);
3 changes: 3 additions & 0 deletions packages/n4s/src/runtime/rules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { isBlank, isNotBlank } from 'isBlank';
import { isBoolean, isNotBoolean } from 'isBoolean';
import { isEmpty, isNotEmpty } from 'isEmpty';
import { isEven } from 'isEven';
import { isKeyOf, isNotKeyOf } from 'isKeyOf';
import { isNaN, isNotNaN } from 'isNaN';
import { isPositive, isNegative } from 'isNegative';
import { isNull, isNotNull } from 'isNull';
Expand Down Expand Up @@ -53,13 +54,15 @@ export default function rules() {
isEmpty,
isEven,
isFalsy,
isKeyOf,
isNaN,
isNegative,
isNotArray,
isNotBetween,
isNotBlank,
isNotBoolean,
isNotEmpty,
isNotKeyOf,
isNotNaN,
isNotNull,
isNotNullish,
Expand Down
1 change: 1 addition & 0 deletions tsconfig.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

51 changes: 51 additions & 0 deletions website/docs/enforce/enforce_rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ Enforce rules are functions that allow you to test your data against different c
- [isPositive](#ispositive)
- [isValueOf](#isvalueof)
- [isNotValueOf](#isnotvalueof)
- [isKeyOf](#iskeyof)
- [isNotKeyOf](#isnotkeyof)

## equals

Expand Down Expand Up @@ -1358,3 +1360,52 @@ enforce('Delta').isNotValueOf({ a: 'Alpha', b: 'Bravo', c: 'Charlie' });
enforce('Bravo').isNotValueOf({ a: 'Alpha', b: 'Bravo', c: 'Charlie' });
// throws
```

## isKeyOf

### Description

Determines whether a value is a key of an object

### Usage examples:

```js
enforce('bananas').isKeyOf({ bananas: 5 });
enforce(1976).isKeyOf({ 1976: 'Rocky' });

// passes
```

```js
enforce('avocados').isKeyOf({ cantelopes: 5 });
enforce(1967).isKeyOf({ 1988: 'Rain Man' });
enforce('key').isKeyOf(undefined);
enforce(15).isKeyOf(null);
enforce('star').isKeyOf(false);
enforce('triangle').isKeyOf(true);
// throws
```

## isNotKeyOf

### Description

Determines whether a value **is not** a key of an object

### Usage examples:

```js
enforce('avocados').isNotKeyOf({ cantelopes: 5 });
enforce(1967).isNotKeyOf({ 1988: 'Rain Man' });
enforce('key').isNotKeyOf(undefined);
enforce(15).isNotKeyOf(null);
enforce('star').isNotKeyOf(false);
enforce('triangle').isNotKeyOf(true);
// passes
```

```js
enforce('bananas').isNotKeyOf({ bananas: 5 });
enforce(1976).isNotKeyOf({ 1976: 'Rocky' });
// throws
```

0 comments on commit 8192b5b

Please sign in to comment.