Why does
val fabOpen = view.findViewById(R.id.fab_open) as FloatingActionButton
work correctly and not error out but the kotlin synthetic of
val fabOpen = R.id.fab_open as FloatingActionButton
gives me the
java.lang.Integer cannot be cast to android.support.design.widget.FloatingActionButton
error? They both show that they are casting as FloatingActionButton. Using the synthetics is not only less code, it's better memory management and I'd prefer to do it this way. Is there something I am missing?
****Update**** I forgot to mention I am trying access the FloatingActionButton inside of a fragment if that makes a difference.
R.id.fab_open is a generated integer value that will be set as the ID of your button at inflation, and that you can look up with findViewById like you've shown.
Casting this to a button won't work, think (FloatingActionButton) 2688664731 in Java terms.
If you wish to use Kotlin Android Extensions and its synthetic properties, those are simply named as the ID itself, but they don't come from the R class - and you don't need to assign them to variables or properties. You can simply use your button like this:
fab_open.setOnClickListener { ... }
fab_open.visibility = View.VISIBLE
I figured out the issue.
to access an element in a view using kotlin synthetic it looks like this:
import kotlinx.android.synthetic.main.chatter_main.view.*
class ChatterMain : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.chatter_main, container, false)
return view
}
Above I imported the kotlin synthetic of the view, inflated the view, and
then I accessed the ID of the element like this:
view.fab_open.visibility = GONE or view.fab_open.SetOnClickListener {}
With the Kotlin Synthetic, you don't need to use:
val fabOpen = R.id.fab_open as FloatingActionButton so I removed that statement.
Related
I have an interface that looks like that:
interface MyObject {
val id: String
val media: MutableList<Uri>
}
I would like to make an implementation of it where the media list is backed by a MutableList<String> instead of MutableList<Uri> (the reason I need that is explained in my long question here). The easy way is:
data class MyObjectPojo(
override val id: String,
val mediaStringList: MutableList<String>
) : Tale {
override val media: MutableList<Uri>
get() = mediaStringList.map { Uri.parse(it) } as MutableList<Uri>
}
But it's obviously inefficient (e.g. in order to get only the first element, a map operation would run for the whole list). I thought about get() = object : MutableList<Uri> {...}, But I realized I have to implement more then 20 members... Is there any nicer way to achieve that?
One option is to extend AbstractList, which could be as simple as:
val media = object : AbstractList<URL>() {
override val size get() = mediaStringList.size
override fun get(index: Int) = Uri.parse(mediaStringList[index])
}
That gives you a read-only view of the underlying mediaStringList: any changes to that are immediately reflected in the view.
Like most performance issues, it's a trade-off: it doesn't store any data itself, but needs to create a new Uri each time an item is retrieved. So it's a good idea only when you need to save memory at the expense of extra processing; or when the list is likely to be big compared with the number of items retrieved.
If you want the view to be writable, you could instead extend AbstractMutableList, and override three more methods. (That's left as an exercise :-)
PS. I'd suggest initialising media to this object, rather than creating it in a getter, as the latter will create a new view every time the getter is called, which is wasteful. (If you were concerned about creating even a single view for each MyObjectPojo, you could wrap it in by lazy {…} so that it would only be created the first time it was needed — at the cost of some synchronisation.)
I'm trying to setup a DocumentGroup in my app, but there's no examples out there yet ReferenceFileDocument is for. I know what a FileDocument is, but how are ReferenceFileDocuments different.
In the docs all it says is:
Conformance to ReferenceFileDocument is expected to be thread-safe,
and deserialization and serialization will be done on a background
thread.
There's a hint in the name: ReferenceFileDocument is a document that's a reference type (ie, a class). FileDocument is for a struct based document.
This has an effect on how documents are saved because SwiftUI can just make a copy of the reference type and save it without worrying about you coming along and modifying it during the save, since it's a value type or tree of value types.
With ReferenceFileDocument, there also doesn't seem to be a clear way for the SwiftUI to know when to save, so it depends on you telling it. There's no direct "doc is dirty, save it now" method, so the way you inform SwiftUI that you've done something that requires saving is through the undo manager.
You also need to provide a snapshot method to return a copy of the document that's safe for it to save.
final class QuizDocument: ReferenceFileDocument, ObservableObject {
#Published var quiz: QuizTemplate
init(quiz: QuizTemplate) {
self.quiz = quiz
}
static var readableContentTypes: [UTType] { [.exampleText] }
init(configuration: ReadConfiguration) throws {
guard let data = configuration.file.regularFileContents,
let quiz = try? JSONDecoder().decode(QuizTemplate.self, from: data)
else {
throw CocoaError(.fileReadCorruptFile)
}
self.quiz = quiz
}
// Produce a snapshot suitable for saving. Copy any nested references so they don't
// change while the save is in progress.
func snapshot(contentType: UTType) throws -> QuizTemplate {
return self.quiz
}
// Save the snapshot
func fileWrapper(snapshot: QuizTemplate, configuration: WriteConfiguration) throws -> FileWrapper {
let data = try JSONEncoder().encode(quiz)
return .init(regularFileWithContents: data)
}
}
ReferenceFileDocument is a document type that will auto-save in the background. It is notified of changes via the UndoManager, so in order to use it you must also make your document undo-able.
The only mention I see of it in the docs is here.
Here is a working example.
I am very new to testing and I'm struggling my way through all this new stuff I am learning. Today I want to write a test for a vuetify <v-text-field> component like this:
<v-text-field
v-model="user.caption"
label="Name"
:disabled="!checkPermissionFor('users.write')"
required
/>
my test should handle the following case:
an active, logged in user has a array in vuex store which has his permissions as a array of strings. exactly like this
userRights: ['dashboard', 'imprint', 'dataPrivacy']
the checkPermissionFor() function is doing nothing else then checking the array above with a arr.includes('x')
after it came out the right is not included it gives me a negotiated return which handles the disabled state on that input field.
I want to test this exact scenario.
my test at the moment looks like this:
it('user has no rights to edit other user overview data', () => {
const store = new Vuex.Store({
state: {
ActiveUser: {
userData: {
isLoggedIn: true,
isAdmin: false,
userRights: ['dashboard', 'imprint', 'dataPrivacy']
}
}
}
})
const wrapper = shallowMount(Overview, {
store,
localVue
})
const addUserPermission = wrapper.vm.checkPermissionFor('users.write')
const inputName = wrapper.find(
'HOW TO SELECT A INPUT LIKE THIS? DO I HAVE TO ADD A CLASS FOR IT?'
)
expect(addUserPermission).toBe(false)
expect(inputName.props('disabled')).toBe(false)
})
big questions now:
how can I select a input from vuetify which has no class like in my case
how can I test for "is the input disabled?"
wrapper.find method accepts a query string. You can pass a query string like this :
input[label='Name'] or if you know the exact index you can use this CSS query too : input:nth-of-type(2).
Then find method will return you another wrapper. Wrapper has a property named element which returns the underlying native element.
So you can check if input disabled like this :
const buttonWrapper = wrapper.find("input[label='Name']");
const isDisabled = buttonWrapper.element.disabled === true;
expect(isDisabled ).toBe(true)
For question 1 it's a good idea to put extra datasets into your component template that are used just for testing so you can extract that element - the most common convention is data-testid="test-id".
The reason you should do this instead of relying on the classes and ids and positional selectors or anything like that is because those selectors are likely to change in a way that shouldn't break your test - if in the future you change css frameworks or change an id for some reason, your tests will break even though your component is still working.
If you're (understandably) worried about polluting your markup with all these data-testid attributes, you can use a webpack plugin like https://github.com/emensch/vue-remove-attributes to strip them out of your dev builds. Here's how I use that with laravel mix:
const createAttributeRemover = require('vue-remove-attributes');
if (mix.inProduction()) {
mix.options({
vue: {
compilerOptions: {
modules: [
createAttributeRemover('data-testid')
]
}
}
})
}
as for your second question I don't know I was googling the same thing and I landed here!
I have been tasked with writing a unit test for the following Web API 2 action:
public HttpResponseMessage Get()
{
IEnumerable<KeyValuePair<long, string>> things = _service.GetSomething();
return ActionContext.Request.CreateResponse(things.Select(x => new
{
Thing1 = x.Prop1.ToString(),
Thing2 = x.Prop2
}).ToArray());
}
I am testing the status code and that works fine, but I have not been able to figure out how I can extract the content data and test it. Here's my test so far:
[TestMethod]
public void GetReturnsOkAndExpectedType()
{
var controller = GetTheController();
var response = controller.Get();
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
dynamic responseContent;
Assert.IsTrue(response.TryGetContentValue(out responseContent));
//???? How can I cast/convert responseContent here ????
}
If I debug the test and inspect responseContent in the immediate window, I see this (I have mocked/stubbed in a single fake value for testing):
{<>f__AnonymousType1<string, string>[1]}
[0]: { Thing1 = "123", Thing2 = "unit test" }
I can cast this as an array of object, but if I try and extract the values by their property names, I get an error (immediate window again):
((object[])responseContent)[0].Thing1
'object' does not contain a definition for 'Thing1' and no extension method 'Thing1' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?)
Similarly, if I try to cast and project to an anonymous type of the same shape, it will not compile:
//Thing1 and Thing2 get red-lined here as 'cannot resolve symbol'
var castResult = ((object[]) responseContent).ToList().Select(x => new {x.Thing1, x.Thing2});
I know I can probably achieve what I want to do if I serialize/deserialize everything using something like JsonConvert, but that doesn't seem like the "right" way to do it. I feel like I'm missing something fundamental, here. How can I cast/convert an anonymous type from HttpResponseMessage for unit testing?
As has been said by #Daniel J.G. in the comments above, one option would be to use reflection to fetch the values of your properties. Since you appear to be using MS testing framework another alternative is to use the PrivateObject class to do some of the reflection work for you.
So, you could do something like this in your test:
var poContent = ((object[])responseContent).Select(x => new PrivateObject(x)).ToArray();
Assert.AreEqual("123", poContent[0].GetProperty("Thing1"));
Assert.AreEqual("unit test", poContent[0].GetProperty("Thing2"));
I use console.log() a lot, especially in combination with Ember.inspect(). But there's one thing I miss:
How can I find out the type of an object (Class)?
For example: Getting something like <Sandbox.ApplicationController:ember288> when inspecting Ember.get("controller")?
If you just want the model name (for example app/models/comment.js has the model name comment), you can use thing.constructor.modelName.
For example:
var aComment = this.get('store').createRecord('comment');
aComment.get('constructor.modelName') // => 'comment'
I understand you are looking for a string for debugging purposes, but I originally came to this question wanting to know specifically how to get the type of the object, not a string describing the object.
Using the built in Javascript property constructor will yield the class used to construct the instance. For example you could do:
person = App.Person.create();
person.constructor // returns App.Person
person.constructor.toString() // return "App.Person"
If you get Class, you can usually call toString() (or as a shortcut concat an empty string + '') to get something like <Sandbox.ApplicationController:ember288>
Another useful feature (in chrome) is the dir command.
dir(App.User)
This will give you the full object information, rather than just the name.
Be aware that some of these answers suggested here only work in development. Once your code is in production most of those methods / class names will get minified.
import Model from '#ember-data/model';
export default class Animal extends Model {
// ...
}
So in development:
const model = this.store.createRecord('animal');
model.constructor.name // returns Animal
in production:
const model = this.store.createRecord('animal');
model.constructor.name // returns 'i' (or any other single letter).
To avoid this, use constructor.toString()
const model = this.store.createRecord('animal');
model.constructor.toString() // returns 'model:animal'