I'm trying to use Google Visualizations from Scala.js. I generated the type definitions using TS importer and the relevant portion it generated is:
#js.native
trait ColumnChartOptions extends js.Object {
var aggregationTarget: String = js.native
var animation: TransitionAnimation = js.native
var annotations: ChartAnnotations = js.native
// ... more
}
#js.native
trait TransitionAnimation extends js.Object {
var duration: Double = js.native
var easing: String = js.native
var startup: Boolean = js.native
}
Now, I'm trying to figure out how to actually use this and came up with:
val options = js.Dynamic.literal.asInstanceOf[ColumnChartOptions]
options.animation = js.Dynamic.literal.asInstanceOf[TransitionAnimation] // comment this and the next line and chart will appear
options.animation.duration = 2000
options.title = "Test Chart"
options.width = 400
options.height = 300
This works if I don't set the animation settings, but fails with the chart showing "Maximum call stack size exceeded" if I do.
I debugged, and found the following:
So animation contains a reference to itself, but I don't feel like this should happen based on the code above.
Ideas how to fix it?
Any other suggestions on how to best use the generated types to provide a type-safe way of creating the JavaScript objects which Google Visualizations expects? I tried new ColumnChartOptions {} which looks cleaner than js.Dynamic but that failed with "A Scala.js-defined JS class cannot directly extend a native JS trait."
P.S. I'd like to note that
options.animation = js.Dynamic.literal(
easing = "inAndOut",
startup = true,
duration = 2000
).asInstanceOf[TransitionAnimation]
actually works, but isn't type-safe (a mis-spelling of duration to durration won't be caught).
Your code lacks () when calling literal(), so the fix would be:
val options = js.Dynamic.literal().asInstanceOf[ColumnChartOptions]
options.animation = js.Dynamic.literal().asInstanceOf[TransitionAnimation] // comment this and the next line and chart will appear
In Scala (and therefore in Scala.js), the presence or absence of () is sometimes meaningful. literal is the singleton object literal, whereas literal() calls the method apply() of said object.
Related
I do localization of my iOS SwiftUI app and using XCode Product/Export localizations.. function to create xcloc file. Everything works fine but strings in init() are not detected in shown in xcloc. Is there any way how to add them?
Thanks
You should replace all relevant String types that are initialized with static string literals with LocalizedStringKey, mainly in the funcs and init()s – so for example:
struct MyStruct {
var myVar: LocalizedStringKey
init(var: LocalizedStringKey) {
self.myVar = var
}
...
}
Stringtypes in model data have to stay untouched.
If there are missing cases left you can add them manually to your .strings file by
"original text" = "localized text";
I have written the following code:
function test() {
var spreadsheet = SpreadsheetApp.getActive();
var ui = SpreadsheetApp.getUi();
var testModeStatus = spreadsheet.getSheetByName("Students").getRange("P2:P2").getValues();
if (testModeStatus == 'FALSE') {
ui.alert("This is inside IF and Test Mode Status is "+testModeStatus);
};
ui.alert("This is outside IF and Test Mode Status is "+testModeStatus);
};
In the above code the variable testModeStatus refers to a sheet cell that is a checkbox and can have the value of either TRUE(checked) or FALSE(unchecked).
I want the code inside if to run only when the checkbox is unchecked. But no matter if the checkbox is checked or unchecked, the code inside if never runs and in both cases just the code outside if runs.
Moreover, in both cases the variable testModeStatus shows the correct value in the popping alert message. I mean if the checkbox is checked the variable shows TRUE and if it is unchecked the variable shows FALSE in the popping alert message.
you're comparing apples with oranges
.getValues() returns a bi-dimensional array and "FALSE" is a string.
Since you get a cell, you can use .getValue instead, but do note that GAS parses the boolean into a JS boolean, so, ultimately, the code should be:
function test() {
var spreadsheet = SpreadsheetApp.getActive();
var ui = SpreadsheetApp.getUi();
var testModeStatus = spreadsheet.getSheetByName("Students").getRange("P2:P2").getValue(); // getValue, not values
if (testModeStatus == false) { //false, not "FALSE"
ui.alert("This is inside IF and Test Mode Status is "+testModeStatus);
};
ui.alert("This is outside IF and Test Mode Status is "+testModeStatus);
};
Given the following snippet from my test:
var mockProvider = MockRepository.GenerateMock<IItemProvider>();
var target = new ItemService(mockProvider);
target.SaveItem(item);
Internally target.SaveItem makes a call like this:
provider.SaveItem(new SaveContract(item.Id, user, contents)); where provider is the local name for the mockProvider passed in.
How do I:
Verify provider.SaveItem is called whilst also
Asserting that the values of item.Id, user and contents are as they should be.
I think I might be able to use mockProvider.AssertWasCalled but can't figure out the syntax to set the condition of the parameters passed to the constructor of SaveContract.
TIA
Ok so based on this I did something like the following:
var mockProvider = MockRepository.GenerateMock<IItemProvider>();
var target = new ItemService(mockProvider);
Item testItem = null;
mockProvider.Expect(c => c.SaveItem(Arg<Item>.Is.Anything))
.WhenCalled(call =>
{
testItem = (Item)call.Arguments[0];
});
target.SaveItem(item);//item initialised elsewhere
Assert.AreEqual(item.Id, testItem.Id);
Are there any worthwhile alternatives for Sinon.js?
Thanks.
Testdouble.js
There is also library called testdouble.js. Which is a kind of more object-oriented than sinon.js.
Also, this article from testdouble guys explain the differences between sinon.js and testdouble.js.
Example
var td = require('testdouble');
var fetch = td.function();
td.when(fetch(42)).thenReturn('Jane User');
fetch(42); // -> 'Jane User'
Not quite as advanced, but you can look at Jack.
I just started a new project called candy-wrapper that may be an alternative to Sinon in some instances:
https://www.npmjs.com/package/candy-wrapper
Here are some examples of how to use it, I would love feedback if anyone has any insights as to how to make it better:
var Wrapper = require("candy-wrapper");
// a simple test object
var myDrone = {
name: "DJI",
fly: function(direction) {
return true;
}
}
new Wrapper(myDrone, "name");
new Wrapper(myDrone, "fly");
myDrone.fly("north");
myDrone.fly("west");
// evaluating previous calls through the 'historyList' and 'Filters'
myDrone.fly.historyList.filterFirst().expectCallArgs("north"); // true
myDrone.fly.historyList.filterSecond().expectCallArgs("east"); // false
myDrone.fly.expectReportAllFailtures(); // throws an error about the "east" expecation failing
// modifying behavior using 'Triggers'
myDrone.fly.triggerOnCallArgs("east").actionReturn(false); // will return 'false' when called with "east"
myDrone.fly("east"); // false
myDrone.fly("west"); // true (the default return value)
// working with properties
myDrone.name.triggerOnSet().actionThrowException(new Error("do not set the name"));
myDrone.name = "Bob"; // throws Error: "do not set the name"
var ret = myDrone.name; // ret = "DJI"
I have absolutely no knowledge in Regex whatsoever. Basically what I'm trying to do is have an error class that I can use to call errors (obviously) which looks like this:
package avian.framework.errors
{
public class AvError extends Object
{
// errors
public static const LAYER_WARNING:String = "Warning: {0} is not a valid layer - the default layer _fallback_ has been used as the container for {1}.";
/**
* Constructor
* Places a warning or error into the output console to assist with misuse of the framework
* #param err The error to display
* #param params A list of Objects to use throughout the error message
*/
public function AvError(err:String, ...params)
{
trace(err);
}
}
}
What I want to be able to do is use the LAYER_WARNING like this:
new AvError(AvError.LAYER_WARNING, targetLayer, this);
And have the output be something along the lines of:
Warning: randomLayer is not a valid layer - the default layer _fallback_ has been used as the container for [object AvChild].
The idea is to replace {0} with the first parameter parsed in ...params, {1} with the second, etc.
I've done a bit of research and I think I've worked out that I need to search using this pattern:
var pattern:RegExp = /{\d}/;
You can use StringUtil
var original:String = "Here is my {0} and my {1}!";
var myStr:String = StringUtil.substitute(original, ['first', 'second']);
Using the g flag in RegExp you can create an array containing all of your {x} matches, then loop through this array and replace each of the matches with the appropriate parameter.
Code:
var mystring:String = "{0} went to {1} on {2}";
function replace(str:String, ...params):String
{
var pattern:RegExp = /{\d}/g;
var ar:Array = str.match(pattern);
var i:uint = 0;
for(i; i<ar.length; i++)
{
str = str.split(ar[i]).join(params[i]);
}
return str;
}
trace(replace(mystring, "marty", "work", "friday")); // marty went to work on friday
i'm assuming you want to have several static constants with varying replacement instances ({0}, {1}, {2}, etc.) in each string constant.
something like this should work - sorry, it's untested:
public function AvError(err:String, ...params)
{
var replacementArray:Array = err.match(new RegExp("{\\d}", "g"));
for (var i:int = 0, i < replacementArray.length, i++)
err = err.replace(new RegExp(replacementArray[i], "g"), params[i]);
trace(err);
}
if you do have several static constants with varying replacement instances, you'll want to check for an appropriate matching amount of …params that are passed.