Skip to content
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
124 changes: 124 additions & 0 deletions src/features/expressions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
import { ExprContext } from 'src/features/expressions/ExprContext';
import { ExprVal } from 'src/features/expressions/types';
import { addError, asExpression, canBeExpression } from 'src/features/expressions/validation';
import { getTextResourceByKey } from 'src/language/sharedLanguage';
import { dataSourcesFromState, resolvedLayoutsFromState } from 'src/utils/layout/hierarchy';
import { LayoutNode } from 'src/utils/layout/LayoutNode';
import { LayoutPage } from 'src/utils/layout/LayoutPage';
Expand Down Expand Up @@ -44,6 +45,8 @@ export interface EvalExprInObjArgs<T> {
deleteNonExpressions?: boolean;
}

const altinnWindow = window as unknown as IAltinnWindow;

/**
* Magic key used to indicate a config value for all possible values in an object
*/
Expand Down Expand Up @@ -509,6 +512,127 @@ export const ExprFunctions = {
args: [ExprVal.String] as const,
returns: ExprVal.Any,
}),
round: defineFunc({
impl(number, decimalPoints: number | null): number | null {
if (number === null) {
throw new LookupNotFound(this, `"Value" parameter cannot be null.`);
}

if (decimalPoints !== undefined && decimalPoints !== null) {
const factor = 10 ** decimalPoints;
return Math.round(number * factor) / factor;
}

return Math.round(number);
},
args: [ExprVal.Number, ExprVal.Number] as const,
returns: ExprVal.Number,
}),
text: defineFunc({
impl(key): string | null {
if (key === null) {
throw new LookupNotFound(this, `"Key" parameter cannot be null.`);
}
const state = altinnWindow.reduxStore.getState();
return getTextResourceByKey(key, state.textResources.resources);
},
args: [ExprVal.String] as const,
returns: ExprVal.String,
}),
language: defineFunc({
impl(): string {
const state = altinnWindow.reduxStore.getState();
return state.profile.selectedAppLanguage || state.profile.profile.profileSettingPreference.language;
},
args: [] as const,
returns: ExprVal.String,
}),
contains: defineFunc({
impl(string: string, stringToContain: string): boolean {
if (string === null || stringToContain === null) {
throw new LookupNotFound(this, `"string" or "stringToContain" parameter cannot be null.`);
}

return string.includes(stringToContain);
},
args: [ExprVal.String, ExprVal.String] as const,
returns: ExprVal.Boolean,
}),
notContains: defineFunc({
impl(string: string, stringToNotContain: string): boolean {
if (string === null || stringToNotContain === null) {
throw new LookupNotFound(this, `"string" or "stringToNotContain" parameter cannot be null.`);
}
return !string.includes(stringToNotContain);
},
args: [ExprVal.String, ExprVal.String] as const,
returns: ExprVal.Boolean,
}),
endsWith: defineFunc({
impl(string: string, stringToMatch: string): boolean {
if (string === null || stringToMatch === null) {
throw new LookupNotFound(this, `"string" or "stringToMatch" parameter cannot be null.`);
}
return string.endsWith(stringToMatch);
},
args: [ExprVal.String, ExprVal.String] as const,
returns: ExprVal.Boolean,
}),
startsWith: defineFunc({
impl(string: string, stringToMatch: string): boolean {
if (string === null || stringToMatch === null) {
throw new LookupNotFound(this, `"string" or "stringToMatch" parameter cannot be null.`);
}

return string.startsWith(stringToMatch);
},
args: [ExprVal.String, ExprVal.String] as const,
returns: ExprVal.Boolean,
}),
stringLength: defineFunc({
impl(string: string): number {
if (string === null) {
throw new LookupNotFound(this, `"string" parameter cannot be null.`);
}

return string.length;
},
args: [ExprVal.String] as const,
returns: ExprVal.Number,
}),
commaContains: defineFunc({
impl(commaSeparatedString: string, stringToMatch: string): boolean {
if (commaSeparatedString === null || stringToMatch === null) {
throw new LookupNotFound(this, `"commaSeparatedString" or "stringToMatch" parameter cannot be null.`);
}

// Split the comma separated string into an array and remove whitespace from each part
const parsedToArray = commaSeparatedString.split(',').map((part) => part.trim());
return parsedToArray.includes(stringToMatch);
},
args: [ExprVal.String, ExprVal.String] as const,
returns: ExprVal.Boolean,
}),
lowerCase: defineFunc({
impl(string: string): string {
if (string === null) {
throw new LookupNotFound(this, `"string" parameter cannot be null.`);
}
return string.toLowerCase();
},
args: [ExprVal.String] as const,
returns: ExprVal.String,
}),
upperCase: defineFunc({
impl(string: string): string {
if (string === null) {
throw new LookupNotFound(this, `"string" parameter cannot be null.`);
}
return string.toUpperCase();
},
args: [ExprVal.String] as const,
returns: ExprVal.String,
}),
};

function asNumber(arg: string) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should return true if the comma-separated list contains the given value",
"expression": ["commaContains", "hello, bye, hola, adios", "hola"],
"expects": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should return false if the comma-separated list does not contain the given value",
"expression": ["commaContains", "hello, bye, hola, adios", "Hasta luego"],
"expects": false
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should return true if the comma-separated list contains the given value even if its provided as a number",
"expression": ["commaContains", "40, 50, 60", 40],
"expects": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should not match case sensitive",
"expression": ["contains", "Hello", "hello"],
"expects": false
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should return true if the first string contains the second string",
"expression": ["contains", "abc", "abc"],
"expects": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "should return false if the second string does not contain the first string",
"expression": ["contains", "Hello", "Bye"],
"expects": false
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should return true if the string contains the substring",
"expression": ["contains", "abc", "b"],
"expects": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should be case sensitive and return false if the string does end with the given string but opposite case",
"expression": ["endsWith", "Hello", "LO"],
"expects": false
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should be true when the string ends with the given string (even when the given 'string' is a number)",
"expression": ["endsWith", "Im 40", 40],
"expects": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should be true when the string ends with the specified string",
"expression": ["endsWith", "Hello", "lo"],
"expects": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should be true when the string ends with the specified string, even on exact match",
"expression": ["endsWith", "Hello", "Hello"],
"expects": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should be false when the string does not ends with the specified string",
"expression": ["endsWith", "Hello", "me"],
"expects": false
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should be true when the given number ends with the given digit",
"expression": ["endsWith", 102, 2],
"expects": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "Should return the selected language",
"expression": ["language"],
"expects": "nb",
"frontendSettings": {
"selectedLanguage": "nb"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should return number as string when number is passed",
"expression": ["lowerCase", 40],
"expects": "40"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should lowercase the string",
"expression": ["lowerCase", "HELLO"],
"expects": "hello"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should lowercase the whole string when given a string has multiple words",
"expression": ["lowerCase", "Hola, Como Estas?"],
"expects": "hola, como estas?"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should lowercase the whole string",
"expression": ["lowerCase", "HElLo"],
"expects": "hello"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should not match case sensitive",
"expression": ["notContains", "Hello", "hello"],
"expects": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should return false when the string does contain the substring",
"expression": ["notContains", "abc", "abc"],
"expects": false
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "should return true if the string does not contain the substring",
"expression": ["notContains", "Hello", "Bye"],
"expects": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should round a number to the nearest integer with a precision of 2",
"expression": ["round", "2.2199999", "2"],
"expects": 2.22
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should round a number to the nearest integer with a precision of 2",
"expression": ["round", 3.2199999, 2],
"expects": 3.22
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should round to nearest integer",
"expression": ["round", 3.2, null],
"expects": 3
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should round negative number",
"expression": ["round", -2.999, null],
"expects": -3
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should be able to round a number to the nearest integer even if it is a string",
"expression": ["round", "3.99", null],
"expects": 4
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should be case sensitive and return false if the string does start with the given string but opposite case",
"expression": ["startsWith", "Hello", "HEL"],
"expects": false
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should be true when the string starts with the specified string, even on exact match",
"expression": ["startsWith", "Hello", "Hello"],
"expects": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should be false when the string does not starts with the specified string",
"expression": ["startsWith", "Hello", "Bye"],
"expects": false
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should be true when the given number starts with the given digit",
"expression": ["startsWith", 102, 1],
"expects": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should be true when the number starts with the given string (number starts with string)",
"expression": ["startsWith", 40, "40"],
"expects": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should be true when the string starts with the given string (even when the given 'string' is a number)",
"expression": ["startsWith", "40 years old", 40],
"expects": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should be true when the string starts with the specified string",
"expression": ["startsWith", "Hello", "Hel"],
"expects": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should return the length of a string even when it's empty",
"expression": ["stringLength", ""],
"expects": 0
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should return the length of a string even if it is type of number",
"expression": ["stringLength", 203],
"expects": 3
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should return the length of a string",
"expression": ["stringLength", "Hello"],
"expects": 5
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should count whitespace as a character when counting string length",
"expression": ["stringLength", " "],
"expects": 1
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should return 'key-name' when key does not exist",
"expression": ["text", "random-key"],
"expects": "random-key"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should UPPERCASE the string",
"expression": ["upperCase", "hello"],
"expects": "HELLO"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should UPPERCASE the whole string when given a string has multiple words",
"expression": ["upperCase", "Hola, como estas?"],
"expects": "HOLA, COMO ESTAS?"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should UPPERCASE the whole string",
"expression": ["upperCase", "heLlo"],
"expects": "HELLO"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Should return number as string when number is passed",
"expression": ["upperCase", 40],
"expects": "40"
}