{
  "$schema": "../cases.schema.json",
  "format": 1,
  "domain": "cei",
  "title": {
    "en": "CEI",
    "pt-BR": "CEI"
  },
  "functions": [
    {
      "id": "cei.format",
      "level": "extended",
      "summary": "Formats a CEI number with the usual \"00.000.00000/00\" mask.",
      "description": "Formats a CEI with the usual mask `00.000.00000/00`.\n\nThe reference implementations of the check digit agree on this mask (the Receita Federal does not print it).\n\n- The mask is applied as far as the digits go, so a value being typed is masked progressively, and digits beyond the 12th are dropped. `options.pad` first left-pads with zeros to 12 digits.\n- A number is read only when it is a safe non-negative integer. A negative, fractional, non-finite or unsafe number gives an empty string (2.4.0 read the digits of any number, sign and decimal point dropped).\n- `options.pad` on a value with no digits (`\"\"`, `\"---\"`, `null`) still gives an empty string. Until 2.4.0 `\"\"` and `\"---\"` gave the whole zero mask.",
      "params": [
        {
          "name": "value",
          "type": "string | number"
        },
        {
          "name": "options",
          "type": "FormatCeiOptions",
          "optional": true
        }
      ],
      "returns": "string",
      "cases": [
        {
          "id": "cei.format#[\"277297118187\"]",
          "args": [
            "277297118187"
          ],
          "expect": {
            "returns": "27.729.71181/87"
          }
        },
        {
          "id": "cei.format#already-formatted",
          "args": [
            "11.583.00249/85"
          ],
          "expect": {
            "returns": "11.583.00249/85"
          }
        },
        {
          "id": "cei.format#partial",
          "args": [
            "27729"
          ],
          "expect": {
            "returns": "27.729"
          }
        },
        {
          "id": "cei.format#empty",
          "args": [
            ""
          ],
          "expect": {
            "returns": ""
          }
        },
        {
          "id": "cei.format#[249859674386]",
          "args": [
            249859674386
          ],
          "expect": {
            "returns": "24.985.96743/86"
          },
          "note": "JavaScript's own test: should format a number input"
        },
        {
          "id": "cei.format#[\"2\"]",
          "args": [
            "2"
          ],
          "expect": {
            "returns": "2"
          },
          "note": "JavaScript's own test: should format progressively as digits are typed"
        },
        {
          "id": "cei.format#[\"27\"]",
          "args": [
            "27"
          ],
          "expect": {
            "returns": "27"
          },
          "note": "JavaScript's own test: should format progressively as digits are typed"
        },
        {
          "id": "cei.format#[\"277\"]",
          "args": [
            "277"
          ],
          "expect": {
            "returns": "27.7"
          },
          "note": "JavaScript's own test: should format progressively as digits are typed"
        },
        {
          "id": "cei.format#[\"2772\"]",
          "args": [
            "2772"
          ],
          "expect": {
            "returns": "27.72"
          },
          "note": "JavaScript's own test: should format progressively as digits are typed"
        },
        {
          "id": "cei.format#[\"277297\"]",
          "args": [
            "277297"
          ],
          "expect": {
            "returns": "27.729.7"
          },
          "note": "JavaScript's own test: should format progressively as digits are typed"
        },
        {
          "id": "cei.format#[\"2772971181870000\"]",
          "args": [
            "2772971181870000"
          ],
          "expect": {
            "returns": "27.729.71181/87"
          },
          "note": "JavaScript's own test: should truncate values longer than 12 digits"
        },
        {
          "id": "cei.format#[\"249\",{\"pad\":true}]",
          "args": [
            "249",
            {
              "pad": true
            }
          ],
          "expect": {
            "returns": "00.000.00002/49"
          },
          "note": "JavaScript's own test: should pad the value with leading zeros when options.pad is true"
        },
        {
          "id": "cei.format#[-1]",
          "args": [
            -1
          ],
          "expect": {
            "returns": ""
          },
          "note": "JavaScript's own test: should return an empty string when it is a negative, fractional or unsafe number (#593 number rule)"
        },
        {
          "id": "cei.format#[1.5]",
          "args": [
            1.5
          ],
          "expect": {
            "returns": ""
          },
          "note": "JavaScript's own test: should return an empty string when it is a negative, fractional or unsafe number (#593 number rule)"
        },
        {
          "id": "cei.format#[9007199254740992]",
          "args": [
            9007199254740992
          ],
          "expect": {
            "returns": ""
          },
          "note": "JavaScript's own test: should return an empty string when it is a negative, fractional or unsafe number (#593 number rule)"
        },
        {
          "id": "cei.format#[\"\",{\"pad\":true}]",
          "args": [
            "",
            {
              "pad": true
            }
          ],
          "expect": {
            "returns": ""
          },
          "note": "changed in 2.5.0 (#615): should return an empty string for a value without digits even when padding; 2.4.0 returned the zero mask"
        },
        {
          "id": "cei.format#[\"---\",{\"pad\":true}]",
          "args": [
            "---",
            {
              "pad": true
            }
          ],
          "expect": {
            "returns": ""
          },
          "note": "changed in 2.5.0 (#615): a value with no digits gives an empty string even with pad"
        },
        {
          "id": "cei.format#[null,{\"pad\":true}]",
          "args": [
            null,
            {
              "pad": true
            }
          ],
          "expect": {
            "returns": ""
          },
          "note": "a null value gives an empty string even with pad (2.4.0 did the same)"
        },
        {
          "id": "cei.format#[-249859674386]",
          "args": [
            -249859674386
          ],
          "expect": {
            "returns": ""
          },
          "note": "JavaScript docs example: not a non-negative safe integer"
        },
        {
          "id": "cei.format#[\"249\"]",
          "args": [
            "249"
          ],
          "expect": {
            "returns": "24.9"
          },
          "note": "JavaScript docs example: no padding by default"
        }
      ]
    },
    {
      "id": "cei.isValid",
      "level": "extended",
      "summary": "Checks whether a CEI number is valid.",
      "description": "Validates a CEI: 12 digits, 11 base digits and one check digit.\n\n- The check digit weights the base by 7, 4, 1, 8, 5, 2, 1, 6, 3, 7, 4. It adds the tens of the sum to its units. Then it takes the complement to 10 of the resulting units digit (10 maps to 0).\n- A value whose digits are all the same is rejected.\n- Accepts a number or a string, unmasked or split into the printed groups (2, 3, 5 and 2 digits) by any run of whitespace, `.`, `-` or `/` between two groups. Whitespace around the value is ignored. Anything else, such as another separator, a letter or a different grouping, is rejected.\n- A number is read only when it is a safe non-negative integer. A negative, fractional, non-finite or unsafe number is invalid.\n- No official source publishes the check digit rule. Only the 12 positions and the CNO keeping the CEI number (Manual de Orientação do eSocial S-1.3, item 9.1) are official. The IN RFB 2.061/2021 has no check digit, and the eSocial only checks that the number exists in the Receita Federal base. The rule comes from third-party reference implementations, cross-checked against the CNO open data and SERPRO's example `000000336854`.\n- A number loses its leading zeros, so a value that starts with `0` is only accepted as a string: `\"000000336854\"` is valid and `336854` is not.",
      "params": [
        {
          "name": "value",
          "type": "string | number"
        }
      ],
      "returns": "boolean",
      "cases": [
        {
          "id": "cei.isValid#[\"11.583.00249/85\"]",
          "args": [
            "11.583.00249/85"
          ],
          "expect": {
            "returns": true
          }
        },
        {
          "id": "cei.isValid#[\"115830024985\"]",
          "args": [
            "115830024985"
          ],
          "expect": {
            "returns": true
          }
        },
        {
          "id": "cei.isValid#[\"277297118187\"]",
          "args": [
            "277297118187"
          ],
          "expect": {
            "returns": true
          }
        },
        {
          "id": "cei.isValid#wrong-check-digit",
          "args": [
            "115830024984"
          ],
          "expect": {
            "returns": false
          }
        },
        {
          "id": "cei.isValid#zeros",
          "args": [
            "000000000000"
          ],
          "expect": {
            "returns": false
          }
        },
        {
          "id": "cei.isValid#too-short",
          "args": [
            "1234567890"
          ],
          "expect": {
            "returns": false
          }
        },
        {
          "id": "cei.isValid#letters",
          "args": [
            "aa.583.00249/85"
          ],
          "expect": {
            "returns": false
          }
        },
        {
          "id": "cei.isValid#empty",
          "args": [
            ""
          ],
          "expect": {
            "returns": false
          }
        },
        {
          "id": "cei.isValid#[\"1234567890123\"]",
          "args": [
            "1234567890123"
          ],
          "expect": {
            "returns": false
          },
          "note": "JavaScript's own test: should return false when it does not have 12 digits"
        },
        {
          "id": "cei.isValid#[\"11#583#00249#85\"]",
          "args": [
            "11#583#00249#85"
          ],
          "expect": {
            "returns": false
          },
          "note": "JavaScript's own test: should return false when it has 12 digits but an unsupported separator"
        },
        {
          "id": "cei.isValid#[\"115.830.02498/5\"]",
          "args": [
            "115.830.02498/5"
          ],
          "expect": {
            "returns": false
          },
          "note": "JavaScript's own test: should return false when it has 12 digits grouped outside the 2-3-5-2 mask"
        },
        {
          "id": "cei.isValid#[\"11.583.00249/85a\"]",
          "args": [
            "11.583.00249/85a"
          ],
          "expect": {
            "returns": false
          },
          "note": "JavaScript's own test: should return false when a valid registration is followed or preceded by a letter"
        },
        {
          "id": "cei.isValid#[\"a11.583.00249/85\"]",
          "args": [
            "a11.583.00249/85"
          ],
          "expect": {
            "returns": false
          },
          "note": "JavaScript's own test: should return false when a valid registration is followed or preceded by a letter"
        },
        {
          "id": "cei.isValid#[\"111111111111\"]",
          "args": [
            "111111111111"
          ],
          "expect": {
            "returns": false
          },
          "note": "JavaScript's own test: should return false when every digit is the same"
        },
        {
          "id": "cei.isValid#[\"24.985.96743/68\"]",
          "args": [
            "24.985.96743/68"
          ],
          "expect": {
            "returns": false
          },
          "note": "JavaScript's own test: should return false when the check digit does not match (24.985.96743/68, yiibr/yii2-br-validator and marcos-cruz/Documento invalid case)"
        },
        {
          "id": "cei.isValid#[\"249859674368\"]",
          "args": [
            "249859674368"
          ],
          "expect": {
            "returns": false
          },
          "note": "JavaScript's own test: should return false when the check digit does not match (24.985.96743/68, yiibr/yii2-br-validator and marcos-cruz/Documento invalid case)"
        },
        {
          "id": "cei.isValid#[\"27.729.71181/87\"]",
          "args": [
            "27.729.71181/87"
          ],
          "expect": {
            "returns": true
          },
          "note": "JavaScript's own test: should return true for 27.729.71181/87 (yiibr/yii2-br-validator CeiValidatorTest)"
        },
        {
          "id": "cei.isValid#[\"24.985.96743/86\"]",
          "args": [
            "24.985.96743/86"
          ],
          "expect": {
            "returns": true
          },
          "note": "JavaScript's own test: should return true for 24.985.96743/86 (marcos-cruz/Documento CeiTest)"
        },
        {
          "id": "cei.isValid#[\"20.381.44217/87\"]",
          "args": [
            "20.381.44217/87"
          ],
          "expect": {
            "returns": true
          },
          "note": "JavaScript's own test: should return true for 20.381.44217/87 (marcos-cruz/Documento CeiTest)"
        },
        {
          "id": "cei.isValid#[\"27.247.25187/86\"]",
          "args": [
            "27.247.25187/86"
          ],
          "expect": {
            "returns": true
          },
          "note": "JavaScript's own test: should return true for 27.247.25187/86 (marcos-cruz/Documento CeiTest)"
        },
        {
          "id": "cei.isValid#[249859674386]",
          "args": [
            249859674386
          ],
          "expect": {
            "returns": true
          },
          "note": "JavaScript's own test: should return true for a number input"
        },
        {
          "id": "cei.isValid#[\" 11 583 00249 85 \"]",
          "args": [
            " 11 583 00249 85 "
          ],
          "expect": {
            "returns": true
          },
          "note": "JavaScript's own test: should return true for a whitespace mask and surrounding whitespace"
        },
        {
          "id": "cei.isValid#[-277297118187]",
          "args": [
            -277297118187
          ],
          "expect": {
            "returns": false
          },
          "note": "JavaScript's own test: should return false when it is a negative or fractional number (#593 number rule)"
        },
        {
          "id": "cei.isValid#[2772971181.87]",
          "args": [
            2772971181.87
          ],
          "expect": {
            "returns": false
          },
          "note": "JavaScript's own test: should return false when it is a negative or fractional number (#593 number rule)"
        },
        {
          "id": "cei.isValid#[\"000000336854\"]",
          "args": [
            "000000336854"
          ],
          "expect": {
            "returns": true
          },
          "note": "SERPRO's example of the CNO cadastro, which keeps the CEI numbering"
        },
        {
          "id": "cei.isValid#[336854]",
          "args": [
            336854
          ],
          "expect": {
            "returns": false
          },
          "note": "JavaScript docs example: a number loses its leading zeros"
        },
        {
          "id": "cei.isValid#[-249859674386]",
          "args": [
            -249859674386
          ],
          "expect": {
            "returns": false
          },
          "note": "JavaScript docs example: not a non-negative safe integer"
        }
      ]
    },
    {
      "id": "cei.parse",
      "level": "extended",
      "summary": "Removes the formatting characters of a CEI and returns only the digits.",
      "description": "Removes CEI formatting and keeps only digits, capped at 12 digits.\n\n- A number is read only when it is a safe non-negative integer. A negative, fractional, non-finite or unsafe number gives an empty string (2.4.0 read the digits of any number, sign and decimal point dropped).",
      "params": [
        {
          "name": "value",
          "type": "string | number"
        }
      ],
      "returns": "string",
      "cases": [
        {
          "id": "cei.parse#masked",
          "args": [
            "27.729.71181/87"
          ],
          "expect": {
            "returns": "277297118187"
          }
        },
        {
          "id": "cei.parse#unmasked",
          "args": [
            "277297118187"
          ],
          "expect": {
            "returns": "277297118187"
          }
        },
        {
          "id": "cei.parse#strips-non-digits",
          "args": [
            "27.?ABC729.71181/87abc"
          ],
          "expect": {
            "returns": "277297118187"
          }
        },
        {
          "id": "cei.parse#empty",
          "args": [
            ""
          ],
          "expect": {
            "returns": ""
          }
        },
        {
          "id": "cei.parse#caps-length",
          "args": [
            "277297118187999"
          ],
          "expect": {
            "returns": "277297118187"
          },
          "note": "reference truncates to the 12 characters of the document; asserted by the reference (JS) unit tests"
        },
        {
          "id": "cei.parse#[277297118187]",
          "args": [
            277297118187
          ],
          "expect": {
            "returns": "277297118187"
          },
          "note": "JavaScript's own test: should read a number as the string of its digits"
        },
        {
          "id": "cei.parse#[-1]",
          "args": [
            -1
          ],
          "expect": {
            "returns": ""
          },
          "note": "JavaScript's own test: should return an empty string when it is a negative, fractional or unsafe number (#593 number rule)"
        },
        {
          "id": "cei.parse#[1.5]",
          "args": [
            1.5
          ],
          "expect": {
            "returns": ""
          },
          "note": "JavaScript's own test: should return an empty string when it is a negative, fractional or unsafe number (#593 number rule)"
        },
        {
          "id": "cei.parse#[9007199254740992]",
          "args": [
            9007199254740992
          ],
          "expect": {
            "returns": ""
          },
          "note": "JavaScript's own test: should return an empty string when it is a negative, fractional or unsafe number (#593 number rule)"
        }
      ]
    }
  ]
}
