Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
M
Metabase
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Engineering Digital Service
Metabase
Commits
aa0a5d99
Commit
aa0a5d99
authored
7 years ago
by
Atte Keinänen
Browse files
Options
Downloads
Patches
Plain Diff
Add stubs to dimension spec, add some renaming suggestions
parent
74a1441d
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
frontend/src/metabase-lib/lib/Dimension.js
+9
-0
9 additions, 0 deletions
frontend/src/metabase-lib/lib/Dimension.js
frontend/src/metabase-lib/lib/Dimension.spec.js
+278
-146
278 additions, 146 deletions
frontend/src/metabase-lib/lib/Dimension.spec.js
with
287 additions
and
146 deletions
frontend/src/metabase-lib/lib/Dimension.js
+
9
−
0
View file @
aa0a5d99
...
...
@@ -31,6 +31,10 @@ type DimensionOption = {
/**
* Dimension base class, represents an MBQL field reference.
*
* Used for displaying fields (like Created At) and their "sub-dimensions" (like Hour of day)
* in field lists and active value widgets for filters, aggregations and breakouts.
*
* @abstract
*/
export
default
class
Dimension
{
...
...
@@ -57,6 +61,7 @@ export default class Dimension {
*/
static
parseMBQL
(
mbql
:
ConcreteField
,
metadata
?:
Metadata
):
?
Dimension
{
for
(
const
D
of
DIMENSION_TYPES
)
{
const
dimension
=
D
.
parseMBQL
(
mbql
,
metadata
);
if
(
dimension
!=
null
)
{
return
dimension
;
...
...
@@ -84,6 +89,8 @@ export default class Dimension {
* Sub-dimensions for the provided dimension of this type.
* @abstract
*/
// TODO Atte Keinänen 5/21/17: Rename either this or the instance method with the same name
// Also making it clear in the method name that we're working with sub-dimensions would be good
static
dimensions
(
parent
:
Dimension
):
Dimension
[]
{
return
[];
}
...
...
@@ -100,6 +107,8 @@ export default class Dimension {
* Returns "sub-dimensions" of this dimension.
* @abstract
*/
// TODO Atte Keinänen 5/21/17: Rename either this or the static method with the same name
// Also making it clear in the method name that we're working with sub-dimensions would be good
dimensions
(
DimensionTypes
:
typeof
Dimension
[]
=
DIMENSION_TYPES
):
Dimension
[]
{
...
...
This diff is collapsed.
Click to expand it.
frontend/src/metabase-lib/lib/Dimension.spec.js
+
278
−
146
View file @
aa0a5d99
...
...
@@ -10,94 +10,138 @@ import {
}
from
"
metabase/__support__/sample_dataset_fixture
"
;
describe
(
"
Dimension
"
,
()
=>
{
it
(
"
should parse and format MBQL correctly
"
,
()
=>
{
expect
(
Dimension
.
parseMBQL
(
1
).
mbql
()).
toEqual
([
"
field-id
"
,
1
]);
expect
(
Dimension
.
parseMBQL
([
"
field-id
"
,
1
]).
mbql
()).
toEqual
([
"
field-id
"
,
1
]);
expect
(
Dimension
.
parseMBQL
([
"
fk->
"
,
1
,
2
]).
mbql
()).
toEqual
([
"
fk->
"
,
1
,
2
]);
expect
(
Dimension
.
parseMBQL
([
"
datetime-field
"
,
1
,
"
month
"
]).
mbql
()
).
toEqual
([
"
datetime-field
"
,
[
"
field-id
"
,
1
],
"
month
"
]);
expect
(
Dimension
.
parseMBQL
([
"
datetime-field
"
,
[
"
field-id
"
,
1
],
"
month
"
]).
mbql
()
).
toEqual
([
"
datetime-field
"
,
[
"
field-id
"
,
1
],
"
month
"
]);
expect
(
Dimension
.
parseMBQL
([
"
datetime-field
"
,
[
"
fk->
"
,
1
,
2
],
"
month
"
]).
mbql
()
).
toEqual
([
"
datetime-field
"
,
[
"
fk->
"
,
1
,
2
],
"
month
"
]);
});
describe
(
"
isEqual
"
,
()
=>
{
it
(
"
should return true for equivalent field-ids
"
,
()
=>
{
const
d1
=
Dimension
.
parseMBQL
(
1
);
const
d2
=
Dimension
.
parseMBQL
([
"
field-id
"
,
1
]);
expect
(
d1
.
isEqual
(
d2
)).
toEqual
(
true
);
expect
(
d1
.
isEqual
([
"
field-id
"
,
1
])).
toEqual
(
true
);
expect
(
d1
.
isEqual
(
1
)).
toEqual
(
true
);
});
it
(
"
should return false for different type clauses
"
,
()
=>
{
const
d1
=
Dimension
.
parseMBQL
([
"
fk->
"
,
1
,
2
]);
const
d2
=
Dimension
.
parseMBQL
([
"
field-id
"
,
1
]);
expect
(
d1
.
isEqual
(
d2
)).
toEqual
(
false
);
});
it
(
"
should return false for same type clauses with different arguments
"
,
()
=>
{
const
d1
=
Dimension
.
parseMBQL
([
"
fk->
"
,
1
,
2
]);
const
d2
=
Dimension
.
parseMBQL
([
"
fk->
"
,
1
,
3
]);
expect
(
d1
.
isEqual
(
d2
)).
toEqual
(
false
);
describe
(
"
STATIC METHODS
"
,
()
=>
{
describe
(
"
parseMBQL(mbql metadata)
"
,
()
=>
{
it
(
"
parses and format MBQL correctly
"
,
()
=>
{
expect
(
Dimension
.
parseMBQL
(
1
,
metadata
).
mbql
()).
toEqual
([
"
field-id
"
,
1
]);
expect
(
Dimension
.
parseMBQL
([
"
field-id
"
,
1
],
metadata
).
mbql
()).
toEqual
([
"
field-id
"
,
1
]);
expect
(
Dimension
.
parseMBQL
([
"
fk->
"
,
1
,
2
],
metadata
).
mbql
()).
toEqual
([
"
fk->
"
,
1
,
2
]);
expect
(
Dimension
.
parseMBQL
([
"
datetime-field
"
,
1
,
"
month
"
],
metadata
).
mbql
()
).
toEqual
([
"
datetime-field
"
,
[
"
field-id
"
,
1
],
"
month
"
]);
expect
(
Dimension
.
parseMBQL
([
"
datetime-field
"
,
[
"
field-id
"
,
1
],
"
month
"
],
metadata
).
mbql
()
).
toEqual
([
"
datetime-field
"
,
[
"
field-id
"
,
1
],
"
month
"
]);
expect
(
Dimension
.
parseMBQL
([
"
datetime-field
"
,
[
"
fk->
"
,
1
,
2
],
"
month
"
],
metadata
).
mbql
()
).
toEqual
([
"
datetime-field
"
,
[
"
fk->
"
,
1
,
2
],
"
month
"
]);
});
})
describe
(
"
isEqual(other)
"
,
()
=>
{
it
(
"
returns true for equivalent field-ids
"
,
()
=>
{
const
d1
=
Dimension
.
parseMBQL
(
1
,
metadata
);
const
d2
=
Dimension
.
parseMBQL
([
"
field-id
"
,
1
],
metadata
);
expect
(
d1
.
isEqual
(
d2
)).
toEqual
(
true
);
expect
(
d1
.
isEqual
([
"
field-id
"
,
1
])).
toEqual
(
true
);
expect
(
d1
.
isEqual
(
1
)).
toEqual
(
true
);
});
it
(
"
returns false for different type clauses
"
,
()
=>
{
const
d1
=
Dimension
.
parseMBQL
([
"
fk->
"
,
1
,
2
],
metadata
);
const
d2
=
Dimension
.
parseMBQL
([
"
field-id
"
,
1
],
metadata
);
expect
(
d1
.
isEqual
(
d2
)).
toEqual
(
false
);
});
it
(
"
returns false for same type clauses with different arguments
"
,
()
=>
{
const
d1
=
Dimension
.
parseMBQL
([
"
fk->
"
,
1
,
2
],
metadata
);
const
d2
=
Dimension
.
parseMBQL
([
"
fk->
"
,
1
,
3
],
metadata
);
expect
(
d1
.
isEqual
(
d2
)).
toEqual
(
false
);
});
});
});
})
describe
(
"
INSTANCE METHODS
"
,
()
=>
{
describe
(
"
dimensions()
"
,
()
=>
{
it
(
"
returns `dimension_options` of the underlying field if available
"
,
()
=>
{
pending
();
})
it
(
"
returns sub-dimensions for matching dimension if no `dimension_options`
"
,
()
=>
{
// just a single scenario should be sufficient here as we will test
// `static dimensions()` individually for each dimension
pending
();
})
})
describe
(
"
isSameBaseDimension(other)
"
,
()
=>
{
it
(
"
returns true if the base dimensions are same
"
,
()
=>
{
pending
();
})
it
(
"
returns false if the base dimensions don't match
"
,
()
=>
{
pending
();
})
})
})
describe
(
"
INSTANCE METHODS
"
,
()
=>
{
describe
(
"
dimensions()
"
,
()
=>
{
it
(
"
returns `default_dimension_option` of the underlying field if available
"
,
()
=>
{
pending
();
})
it
(
"
returns default dimension for matching dimension if no `default_dimension_option`
"
,
()
=>
{
// just a single scenario should be sufficient here as we will test
// `static defaultDimension()` individually for each dimension
pending
();
})
})
})
});
describe
(
"
FieldI
d
Dimension
"
,
()
=>
{
describe
(
"
FieldI
D
Dimension
"
,
()
=>
{
const
dimension
=
Dimension
.
parseMBQL
(
[
"
field-id
"
,
ORDERS_TOTAL_FIELD_ID
],
metadata
);
describe
(
"
mbql
"
,
()
=>
{
it
(
'
should return a "field-id" clause
'
,
()
=>
{
expect
(
dimension
.
mbql
()).
toEqual
([
"
field-id
"
,
ORDERS_TOTAL_FIELD_ID
]);
describe
(
"
INSTANCE METHODS
"
,
()
=>
{
describe
(
"
mbql()
"
,
()
=>
{
it
(
'
returns a "field-id" clause
'
,
()
=>
{
expect
(
dimension
.
mbql
()).
toEqual
([
"
field-id
"
,
ORDERS_TOTAL_FIELD_ID
]);
});
});
});
describe
(
"
displayN
ame
"
,
()
=>
{
it
(
"
should return the field name
"
,
()
=>
{
expect
(
dimension
.
displayName
()).
toEqual
(
"
Total
"
);
describe
(
"
displayName()
"
,
()
=>
{
it
(
"
returns the field n
ame
"
,
()
=>
{
expect
(
dimension
.
displayName
()).
toEqual
(
"
Total
"
);
}
);
});
});
describe
(
"
subDisplayName
"
,
()
=>
{
it
(
"
should return 'Continuous (no binning)' for numeric fields
"
,
()
=>
{
expect
(
dimension
.
subDisplayName
()).
toEqual
(
"
Continuous (no binning)
"
);
});
it
(
"
should return 'Default' for non-numeric fields
"
,
()
=>
{
expect
(
Dimension
.
parseMBQL
(
[
"
field-id
"
,
PRODUCT_CATEGORY_FIELD_ID
],
metadata
).
subDisplayName
()
).
toEqual
(
"
Default
"
);
describe
(
"
subDisplayName()
"
,
()
=>
{
it
(
"
returns 'Continuous (no binning)' for numeric fields
"
,
()
=>
{
expect
(
dimension
.
subDisplayName
()).
toEqual
(
"
Continuous (no binning)
"
);
}
);
it
(
"
returns 'Default' for non-numeric fields
"
,
()
=>
{
expect
(
Dimension
.
parseMBQL
(
[
"
field-id
"
,
PRODUCT_CATEGORY_FIELD_ID
],
metadata
).
subDisplayName
()
).
toEqual
(
"
Default
"
);
}
);
});
});
describe
(
"
subTriggerDisplayNam
e
"
,
()
=>
{
it
(
"
should not have a value
"
,
()
=>
{
expect
(
dimension
.
subTriggerDisplayName
()).
toBeFalsy
(
);
describe
(
"
subTriggerDisplayName()
"
,
()
=>
{
it
(
"
does not have a valu
e
"
,
()
=>
{
expect
(
dimension
.
subTriggerDisplayName
()).
toBeFalsy
();
}
);
});
})
;
})
});
describe
(
"
FKDimension
"
,
()
=>
{
...
...
@@ -105,30 +149,47 @@ describe("FKDimension", () => {
[
"
fk->
"
,
ORDERS_PRODUCT_FK_FIELD_ID
,
PRODUCT_TILE_FIELD_ID
],
metadata
);
describe
(
"
mbql
"
,
()
=>
{
it
(
'
should return a "fk->" clause
'
,
()
=>
{
expect
(
dimension
.
mbql
()).
toEqual
([
"
fk->
"
,
ORDERS_PRODUCT_FK_FIELD_ID
,
PRODUCT_TILE_FIELD_ID
]);
});
describe
(
"
STATIC METHODS
"
,
()
=>
{
describe
(
"
dimensions(parentDimension)
"
,
()
=>
{
it
(
"
should return array of FK dimensions for foreign key field dimension
"
,
()
=>
{
pending
();
// Something like this:
// fieldsInProductsTable = metadata.tables[1].fields.length;
// expect(FKDimension.dimensions(fkFieldIdDimension).length).toEqual(fieldsInProductsTable);
})
it
(
"
should return empty array for non-FK field dimension
"
,
()
=>
{
pending
();
})
})
});
describe
(
"
displayName
"
,
()
=>
{
it
(
"
should return the field name
"
,
()
=>
{
expect
(
dimension
.
displayName
()).
toEqual
(
"
Title
"
);
describe
(
"
INSTANCE METHODS
"
,
()
=>
{
describe
(
"
mbql()
"
,
()
=>
{
it
(
'
returns a "fk->" clause
'
,
()
=>
{
expect
(
dimension
.
mbql
()).
toEqual
([
"
fk->
"
,
ORDERS_PRODUCT_FK_FIELD_ID
,
PRODUCT_TILE_FIELD_ID
]);
});
});
});
describe
(
"
subDisplayN
ame
"
,
()
=>
{
it
(
"
should return the field name
"
,
()
=>
{
expect
(
dimension
.
subDisplayName
()).
toEqual
(
"
Title
"
);
describe
(
"
displayName()
"
,
()
=>
{
it
(
"
returns the field n
ame
"
,
()
=>
{
expect
(
dimension
.
displayName
()).
toEqual
(
"
Title
"
);
}
);
});
});
describe
(
"
subTriggerDisplayN
ame
"
,
()
=>
{
it
(
"
should not have a value
"
,
()
=>
{
expect
(
dimension
.
subTriggerDisplayName
()).
toBeFalsy
(
);
describe
(
"
subDisplayName()
"
,
()
=>
{
it
(
"
returns the field n
ame
"
,
()
=>
{
expect
(
dimension
.
subDisplayName
()).
toEqual
(
"
Title
"
);
}
);
});
});
describe
(
"
subTriggerDisplayName()
"
,
()
=>
{
it
(
"
does not have a value
"
,
()
=>
{
expect
(
dimension
.
subTriggerDisplayName
()).
toBeFalsy
();
});
});
})
});
describe
(
"
DatetimeFieldDimension
"
,
()
=>
{
...
...
@@ -136,30 +197,55 @@ describe("DatetimeFieldDimension", () => {
[
"
datetime-field
"
,
ORDERS_CREATED_DATE_FIELD_ID
,
"
month
"
],
metadata
);
describe
(
"
mbql
"
,
()
=>
{
it
(
'
should return a "datetime-field" clause
'
,
()
=>
{
expect
(
dimension
.
mbql
()).
toEqual
([
"
datetime-field
"
,
[
"
field-id
"
,
ORDERS_CREATED_DATE_FIELD_ID
],
"
month
"
]);
describe
(
"
STATIC METHODS
"
,
()
=>
{
describe
(
"
dimensions(parentDimension)
"
,
()
=>
{
it
(
"
should return an array with dimensions for each datetime unit
"
,
()
=>
{
pending
();
// Something like this:
// fieldsInProductsTable = metadata.tables[1].fields.length;
// expect(FKDimension.dimensions(fkFieldIdDimension).length).toEqual(fieldsInProductsTable);
})
it
(
"
should return empty array for non-date field dimension
"
,
()
=>
{
pending
();
})
})
describe
(
"
defaultDimension(parentDimension)
"
,
()
=>
{
it
(
"
should return dimension with 'day' datetime unit
"
,
()
=>
{
pending
();
})
it
(
"
should return null for non-date field dimension
"
,
()
=>
{
pending
();
})
});
});
describe
(
"
displayName
"
,
()
=>
{
it
(
"
should return the field name
"
,
()
=>
{
expect
(
dimension
.
displayName
()).
toEqual
(
"
Created At
"
);
describe
(
"
INSTANCE METHODS
"
,
()
=>
{
describe
(
"
mbql()
"
,
()
=>
{
it
(
'
returns a "datetime-field" clause
'
,
()
=>
{
expect
(
dimension
.
mbql
()).
toEqual
([
"
datetime-field
"
,
[
"
field-id
"
,
ORDERS_CREATED_DATE_FIELD_ID
],
"
month
"
]);
});
});
});
describe
(
"
subDisplayN
ame
"
,
()
=>
{
it
(
"
should return 'Month'
"
,
()
=>
{
expect
(
dimension
.
subDisplayName
()).
toEqual
(
"
Month
"
);
describe
(
"
displayName()
"
,
()
=>
{
it
(
"
returns the field n
ame
"
,
()
=>
{
expect
(
dimension
.
displayName
()).
toEqual
(
"
Created At
"
);
}
);
});
});
describe
(
"
subTriggerDisplayName
"
,
()
=>
{
it
(
"
should return 'by month'
"
,
()
=>
{
expect
(
dimension
.
subTriggerDisplayName
()).
toEqual
(
"
by month
"
);
describe
(
"
subDisplayName()
"
,
()
=>
{
it
(
"
returns 'Month'
"
,
()
=>
{
expect
(
dimension
.
subDisplayName
()).
toEqual
(
"
Month
"
);
}
);
});
});
describe
(
"
subTriggerDisplayName()
"
,
()
=>
{
it
(
"
returns 'by month'
"
,
()
=>
{
expect
(
dimension
.
subTriggerDisplayName
()).
toEqual
(
"
by month
"
);
});
});
})
});
describe
(
"
BinningStrategyDimension
"
,
()
=>
{
...
...
@@ -167,33 +253,47 @@ describe("BinningStrategyDimension", () => {
[
"
binning-strategy
"
,
ORDERS_TOTAL_FIELD_ID
,
"
default
"
,
10
],
metadata
);
describe
(
"
mbql
"
,
()
=>
{
it
(
'
should return a "binning-strategy" clause
'
,
()
=>
{
expect
(
dimension
.
mbql
()).
toEqual
([
"
binning-strategy
"
,
[
"
field-id
"
,
ORDERS_TOTAL_FIELD_ID
],
"
default
"
,
10
]);
});
describe
(
"
STATIC METHODS
"
,
()
=>
{
describe
(
"
dimensions(parentDimension)
"
,
()
=>
{
it
(
"
should return an array of dimensions based on default binning
"
,
()
=>
{
pending
();
})
it
(
"
should return empty array for non-number field dimension
"
,
()
=>
{
pending
();
})
})
});
describe
(
"
displayName
"
,
()
=>
{
it
(
"
should return the field name
"
,
()
=>
{
expect
(
dimension
.
displayName
()).
toEqual
(
"
Total
"
);
describe
(
"
INSTANCE METHODS
"
,
()
=>
{
describe
(
"
mbql()
"
,
()
=>
{
it
(
'
returns a "binning-strategy" clause
'
,
()
=>
{
expect
(
dimension
.
mbql
()).
toEqual
([
"
binning-strategy
"
,
[
"
field-id
"
,
ORDERS_TOTAL_FIELD_ID
],
"
default
"
,
10
]);
});
});
});
describe
(
"
subDisplayName
"
,
()
=>
{
it
(
"
should return 'Quantized into 10 bins'
"
,
()
=>
{
expect
(
dimension
.
subDisplayName
()).
toEqual
(
"
Quantized into 10 bins
"
);
describe
(
"
displayName()
"
,
()
=>
{
it
(
"
returns the field name
"
,
()
=>
{
expect
(
dimension
.
displayName
()).
toEqual
(
"
Total
"
);
});
});
});
describe
(
"
subTriggerDisplayName
"
,
()
=>
{
it
(
"
should return '10 bins'
"
,
()
=>
{
expect
(
dimension
.
subTriggerDisplayName
()).
toEqual
(
"
10 bins
"
);
describe
(
"
subDisplayName()
"
,
()
=>
{
it
(
"
returns 'Quantized into 10 bins'
"
,
()
=>
{
expect
(
dimension
.
subDisplayName
()).
toEqual
(
"
Quantized into 10 bins
"
);
});
});
});
describe
(
"
subTriggerDisplayName()
"
,
()
=>
{
it
(
"
returns '10 bins'
"
,
()
=>
{
expect
(
dimension
.
subTriggerDisplayName
()).
toEqual
(
"
10 bins
"
);
});
});
})
});
describe
(
"
ExpressionDimension
"
,
()
=>
{
...
...
@@ -201,14 +301,46 @@ describe("ExpressionDimension", () => {
[
"
expression
"
,
"
Hello World
"
],
metadata
);
describe
(
"
mbql
"
,
()
=>
{
it
(
'
should return a "expression" clause
'
,
()
=>
{
expect
(
dimension
.
mbql
()).
toEqual
([
"
expression
"
,
"
Hello World
"
]);
});
describe
(
"
STATIC METHODS
"
,
()
=>
{
describe
(
"
dimensions(parentDimension)
"
,
()
=>
{
it
(
"
should return array of FK dimensions for foreign key field dimension
"
,
()
=>
{
pending
();
// Something like this:
// fieldsInProductsTable = metadata.tables[1].fields.length;
// expect(FKDimension.dimensions(fkFieldIdDimension).length).toEqual(fieldsInProductsTable);
})
it
(
"
should return empty array for non-FK field dimension
"
,
()
=>
{
pending
();
})
})
});
describe
(
"
displayName
"
,
()
=>
{
it
(
"
should return the expression name
"
,
()
=>
{
expect
(
dimension
.
displayName
()).
toEqual
(
"
Hello World
"
);
describe
(
"
INSTANCE METHODS
"
,
()
=>
{
describe
(
"
mbql()
"
,
()
=>
{
it
(
'
returns an "expression" clause
'
,
()
=>
{
expect
(
dimension
.
mbql
()).
toEqual
([
"
expression
"
,
"
Hello World
"
]);
});
});
describe
(
"
displayName()
"
,
()
=>
{
it
(
"
returns the expression name
"
,
()
=>
{
expect
(
dimension
.
displayName
()).
toEqual
(
"
Hello World
"
);
});
});
})
});
describe
(
"
AggregationDimension
"
,
()
=>
{
const
dimension
=
Dimension
.
parseMBQL
(
[
"
aggregation
"
,
1
],
metadata
);
describe
(
"
INSTANCE METHODS
"
,
()
=>
{
describe
(
"
mbql()
"
,
()
=>
{
it
(
'
returns an "aggregation" clause
'
,
()
=>
{
expect
(
dimension
.
mbql
()).
toEqual
([
"
aggregation
"
,
1
]);
});
});
});
});
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment