Error: Couldn't resolve the package 'path_provider' in 'package:path_provider/path_provider.dart' if (dart.library.io) import using - flutter-web

I know that the path_provider is not meant for the web. And I'm trying to separate implementations for web and mobile platforms through imports of the respective files, however, I get an error ONLY when compiling.
Please help me.
Error:
Error: Couldn't resolve the package 'path_provider' in 'package:path_provider/path_provider.dart'.
packages/locale_cache/lib/database/database_helper_mobile.dart:12:8: Error: Not found: 'package:path_provider/path_provider.dart'
import 'package:path_provider/path_provider.dart' as paths;
^
packages/locale_cache/lib/database/database_helper_mobile.dart:21:33: Error: Method not found: 'getApplicationDocumentsDirectory'.
final dir = await paths.getApplicationDocumentsDirectory();
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
packages/locale_cache/lib/database/database_helper_mobile.dart:42:29: Error: Method not found: 'getApplicationDocumentsDirectory'.
final dir = await paths.getApplicationDocumentsDirectory();
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Unhandled exception:
FileSystemException(uri=org-dartlang-untranslatable-uri:package%3Apath_provider%2Fpath_provider.dart; message=StandardFileSystem only supports file:* and data:* URIs)
#0 StandardFileSystem.entityForUri (package:front_end/src/api_prototype/standard_file_system.dart:34:7)
#1 asFileUri (package:vm/kernel_front_end.dart:623:37)
#2 writeDepfile (package:vm/kernel_front_end.dart:763:21)
<asynchronous suspension>
#3 FrontendCompiler.compile (package:frontend_server/frontend_server.dart:586:9)
<asynchronous suspension>
#4 starter (package:flutter_frontend_server/server.dart:85:12)
<asynchronous suspension>
#5 main (file:///C:/b/s/w/ir/cache/builder/src/flutter/flutter_frontend_server/bin/starter.dart:13:24)
<asynchronous suspension>
dependencies:
dev_dependencies:
build_runner: 2.1.7
drift_dev: 1.4.0
flutter_lints: 1.0.0
flutter_test:
sdk: flutter
injectable_generator: 1.5.2
path_provider: 2.0.2
Common file
import 'package:drift/drift.dart';
import 'package:drift/isolate.dart';
import 'package:locale_cache/database/database_getter.dart';
abstract class DatabaseHelper {
factory DatabaseHelper() => getDatabaseHelper();
LazyDatabase createConnection({bool logStatements = false}) => throw Exception('Platform not supported');
Future<DriftIsolate> createDriftIsolate({bool logStatements = false}) async => throw Exception('Platform not supported');
}
database_getter.dart
import 'package:locale_cache/database/database_helper.dart';
DatabaseHelper getDatabaseHelper() => throw UnsupportedError('Cannot create abstract class');
database_helper_web.dart
import 'package:drift/drift.dart';
import 'package:drift/isolate.dart';
import 'package:locale_cache/database/database_helper.dart';
class DatabaseHelperWeb implements DatabaseHelper {
#override
LazyDatabase createConnection({bool logStatements = false}) => throw Exception('Platform not supported');
#override
Future<DriftIsolate> createDriftIsolate({bool logStatements = false}) => throw Exception('Platform not supported');
}
DatabaseHelper getDatabaseHelper() => DatabaseHelperWeb();
database_helper_mobile.dart
import 'dart:async';
import 'dart:io';
import 'dart:isolate';
import 'package:drift/drift.dart';
import 'package:drift/isolate.dart';
import 'package:drift/native.dart';
import 'package:flutter/material.dart';
import 'package:locale_cache/database/database_helper.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart' as paths;
class DatabaseHelperMobile implements DatabaseHelper {
#override
LazyDatabase createConnection({bool logStatements = false}) {
// some work
}
#override
Future<DriftIsolate> createDriftIsolate({bool logStatements = false}) async {
// some work
}
}
DatabaseHelper getDatabaseHelper() => DatabaseHelperMobile();
How I use it
import 'package:locale_cache/database/database_helper.dart' if (dart.library.html) 'database_helper_web.dart' if (dart.library.io) 'database_helper_mobile.dart';
final DatabaseHelper _databaseHelper = DatabaseHelper();
P.s. I have tried flutter clean and pub get

Related

How to initialise a class constructor using inversify which has other dependency

config.ts
export const bindings = new AsyncContainerModule(async (bind) => {
await getDbConnection();
await AppSubscribers;
await Locators;
await RouterClass;
bind<AppSubscribers>(TYPES.AppSubscribers).to(AppSubscribers);
bind<Locators>(TYPES.Locators).to(Locators);
bind<IRepository>(TYPES.IRepository).to(Repository);
locator.ts
import { inject, injectable } from 'inversify';
import TYPES from '#shared/di/types/types';
import Locator from '../.Locators';
import { AfterTypeCreated } from './AfterTypeCreated';
import { logger } from '#shared/core/logger/logger';
export class AppSubscribers {
constructor(
#inject(TYPES.Locators)
private locators: Locators
) {
logger.info('SUBSCRIBER STARTED');
new AfterDataCreated(this._locators);
}
}
AppSubscriber needs to inject Locators which further injects Repo and other services.
I need to initialise app subscriber at the start of the application to add all the subscribers (observers) to the registry.

How to fix "Failed assertion: 'create != null': is not true" error with Provider package in Flutter?

Here is the error message from Android Studio:
════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following assertion was thrown building MyZippyApp(dirty):
'package:provider/src/provider.dart': Failed assertion: line 181 pos 16: 'create != null': is not true.
The relevant error-causing widget was:
MyZippyApp file:///Users/mgav/AndroidStudioProjects/streakers_journal_beta/lib/main.dart:5:23
When the exception was thrown, this was the stack:
#2 new Provider (package:provider/src/provider.dart:181:16)
#3 MyZippyApp.build (package:streakers_journal_beta/main.dart:10:12)
#4 StatelessElement.build (package:flutter/src/widgets/framework.dart:4701:28)
#5 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4627:15)
#6 Element.rebuild (package:flutter/src/widgets/framework.dart:4343:5)
It appears as soon as I wrap 'MaterialApp' in a 'Provider' widget (using package version provider: ^4.3.2 in pubspec.yaml > ran 'Pub get'), then try to run the app.
Here is the main.dart code before wrapping with the 'Provider' widget (works perfectly well):
import 'package:flutter/material.dart';
import 'package:streakers_journal_beta/screens/tasks_screen.dart';
import 'package:provider/provider.dart';
void main() => runApp(MyZippyApp());
class MyZippyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home:
TasksScreen(), // matches "TasksScreen" class created on tasks_screen.dart
);
}
}
Here is the main.dart code after wrapping with the provider widget:
import 'package:flutter/material.dart';
import 'package:streakers_journal_beta/screens/tasks_screen.dart';
import 'package:provider/provider.dart';
void main() => runApp(MyZippyApp());
class MyZippyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Provider(
child: MaterialApp(
home:
TasksScreen(), // matches "TasksScreen" class created on tasks_screen.dart
),
);
}
}
And per Farhan Syah's answer below, here is the revised code that reflects his answer (and fixes the problem):
import 'package:flutter/material.dart';
import 'package:streakers_journal_beta/screens/tasks_screen.dart';
import 'package:provider/provider.dart';
void main() => runApp(MyZippyApp());
class MyZippyApp extends StatelessWidget {
final String testingText = 'Thank you Farhan Syah';
#override
Widget build(BuildContext context) {
return Provider(
create: (context) => testingText,
child: MaterialApp(
home:
TasksScreen(), // matches "TasksScreen" class created on tasks_screen.dart
),
);
}
}
Provider widget has a required create properties.
you should use 'create' to create an object which you want to provide.
return Provider(
create: (context)=> ObjectToBeProvidedHere(),
child: MaterialApp(
home:
TasksScreen(), // matches "TasksScreen" class created on tasks_screen.dart
),
);

How to spy on functions outside a component?

// ./index.js
import { Component } from 'react';
export default class Test extends Component {
method () {
console.log('method()');
}
do () {
this.method();
func();
}
render () {
return null;
}
}
export function func () {
console.log('func()');
}
// ./index.test.js
import { shallow } from 'enzyme';
import React from 'react';
import * as Test from './index';
describe('<Test>', () => {
const component = shallow(<Test.default/>),
method_spy = jest.spyOn(component.instance(), 'method'),
func_spy = jest.spyOn(Test, 'func');
test('func()', () => {
component.instance().do();
expect(method_spy).toHaveBeenCalledTimes(1); // passed
expect(func_spy).toHaveBeenCalledTimes(1); // failed
});
});
I want to spy on function outside a component, but It doesn't work well.
I've got a message like Expected mock function to have been called one time, but it was called zero times.
And I don't want to use mock() method instead of spyOn() in the situation.
Is there way to fix it? Thaks you for reading. :D
It doesn't work because this line:
const func_spy = jest.spyOn(Test, 'func');
...is creating a spy on the module export for func...
...but Test.do doesn't call the module export for func, it calls func directly.
There are two options to fix it.
One is to move func into its own module.
Then the module export for it will be imported into index.js and called within Test.do...
...and when the module export for func is wrapped in a spy the spy will get called by Test.do.
The other option is to note that "ES6 modules support cyclic dependencies automatically" so a module can be imported into itself.
If the module is imported into itself then Test.do can call the module export for func:
import { Component } from 'react';
import * as index from './index'; // <= import the module into itself
export default class Test extends Component {
method() {
console.log('method()');
}
do() {
this.method();
index.func(); // <= use the module
}
render() {
return null;
}
}
export function func() {
console.log('func()');
}
...and the spy on the module export for func will be called as expected:
import { shallow } from 'enzyme';
import React from 'react';
import * as Test from './index';
describe('<Test>', () => {
const component = shallow(<Test.default />),
method_spy = jest.spyOn(component.instance(), 'method'),
func_spy = jest.spyOn(Test, 'func');
test('func()', () => {
component.instance().do();
expect(method_spy).toHaveBeenCalledTimes(1); // Success!
expect(func_spy).toHaveBeenCalledTimes(1); // Success!
});
});

tests fail when injecting a class with decorator

This is likely an environment issue on my end, but I'm having problems testing injected classes that use decorators.
Am hoping someone can see what I'm missing.
Note: that when I run the code, it runs fine. The error only occurs when running jest tests. I have a full test suite that works fine. The test in question that fails passes when I remove the decorator annotation and no longer have the class extend EventEmitter.
I also use ts-node to run the code. I use ts-node ./node_modules/.bin/jest src/event-emitter-inversify/__tests__/event-emitter-inversify.test.ts
I'm not sure why the tests fail and the run succeeds.
I consistently see the error TypeError: Cannot read property 'constructor' of null in my tests.
Here is the setup.
event-emitter-inversify.ts
import 'reflect-metadata';
import { EventEmitter } from 'events';
import { ContainerModule, decorate, injectable, interfaces } from 'inversify';
decorate(injectable(), EventEmitter);
#injectable()
export class EventEmitterChild extends EventEmitter {
constructor() {
super();
}
greet() {
console.log('hello world.');
}
}
export const EventEmitterModule = new ContainerModule(
(bind: interfaces.Bind) => {
bind<EventEmitterChild>('EventEmitterChild').to(EventEmitterChild).inSingletonScope();
}
);
event-emitter-inversify-dependent.ts
import { inject, injectable } from 'inversify';
import { EventEmitterChild } from './event-emitter-inversify';
#injectable()
export class EventEmitterDependent {
constructor(#inject('EventEmitterChild') private readonly _eventEmitterChild: EventEmitterChild) {
}
run() {
this._eventEmitterChild.greet();
}
}
run.ts (this runs fine!)
import { Container } from 'inversify';
import { EventEmitterChild, EventEmitterModule } from './event-emiiter-inversify';
import { EventEmitterDependent } from './event-emitter-inversify-dependent';
const referenceContainer = new Container();
referenceContainer.load(EventEmitterModule);
const eventEmitterChild = referenceContainer.get<EventEmitterChild>('EventEmitterChild');
eventEmitterChild.greet();
const eventEmitterDependent = referenceContainer.get<EventEmitterDependent>('EventEmitterDependent');
eventEmitterDependent.run();
event-emitter-inversify.test.ts (this fails)
import { Container } from 'inversify';
import { EventEmitterChild, EventEmitterModule } from '../event-emitter-inversify';
describe('EventEmitter test', () => {
const container: Container = new Container();
beforeAll(async () => {
container.load(EventEmitterModule);
});
test('get EventEmitterChild from container', () => {
const eventEmitterChild = container.get<EventEmitterChild>('EventEmitterChild');
expect(eventEmitterChild).toBeDefined();
});
});
I run the test with:
ts-node ./node_modules/.bin/jest src/event-emitter-inversify/__tests__/event-emitter-inversify.test.ts
And it fails with:
TypeError: Cannot read property 'constructor' of null
stacktrace
at getClassPropsAsTargets (node_modules/inversify/lib/planning/reflection_utils.js:82:75)
at getClassPropsAsTargets (node_modules/inversify/lib/planning/reflection_utils.js:84:27)
at getClassPropsAsTargets (node_modules/inversify/lib/planning/reflection_utils.js:84:27)
at getTargets (node_modules/inversify/lib/planning/reflection_utils.js:28:27)
at Object.getDependencies (node_modules/inversify/lib/planning/reflection_utils.js:12:19)
at node_modules/inversify/lib/planning/planner.js:106:51
at Array.forEach (<anonymous>)
at _createSubRequests (node_modules/inversify/lib/planning/planner.js:94:20)
at Object.plan (node_modules/inversify/lib/planning/planner.js:136:9)
at node_modules/inversify/lib/container/container.js:318:37
Any ideas of what I'm missing or doing wrong?

ts2304 cannot find name 'OnInit'

I've worked through the Angular superhero tutorial. It all works.
If i close the cmd window running NPM, then re-open a CMD window and reissue the NPM START command I get two errors
src/app/DashBoard.component.ts(12,44) TS2304 : Cannot find name 'OnInit'.
src/app/hero-list.component.ts(16, 434) TS2304 : Cannot find name 'OnInit'.
I can resolve this by removing
Implements OnInit
from both these classes,
run NPM start
re-add them (simply CTL Z in the editor)
make some change , save.
The app recompiles and I am off and running.
I have 4 classes that implement this function. I have studied them and can not figure out what makes 2 fail...
I have read posts that reference TS2304, but this seems to be a generic Function/Variable/Symbol not found message ...
I don't know what to post. I'm happy to post any of the code.
Is this caused by errors in modules this depends on (hero.ts)?
Here is one class that is failing in this manner.
This is the hero-list.component.ts file
(at various points in the demo/online examples, this is also named Heroes.component..)
import { Component } from '#angular/core';
import { Router } from '#angular/router';
import { Hero } from './hero';
import { HeroService } from './hero.service';
#Component({
selector: 'hero-list',
templateUrl: './hero-list.component.html' ,
providers: [HeroService],
styleUrls: [ './hero-list.component.css']
})
export class HeroListComponent implements OnInit {
heroes : Hero[];
selectedHero: Hero;
constructor(
private router : Router ,
private heroService: HeroService
) { }
ngOnInit(): void {
this.getHeroes();
}
onSelect(hero: Hero): void {
this.selectedHero = hero;
}
getHeroes(): void {
this.heroService.getHeroes().then(heroes => this.heroes = heroes);
}
gotoDetail() {
this.router.navigate(['/detail', this.selectedHero.id]);
}
add(name: string): void {
name = name.trim();
if (!name) { return; }
this.heroService.create(name)
.then(hero => {
this.heroes.push(hero);
this.selectedHero = null;
});
}
delete(hero: Hero): void {
this.heroService
.delete(hero.id)
.then(() => {
this.heroes = this.heroes.filter(h => h !== hero);
if (this.selectedHero === hero) { this.selectedHero = null; }
});
}
}
You have to import OnInit.
import { Component, OnInit } from '#angular/core';
The tutorial fails to mention that you need to add the import of OnInit to TypeScript file app.component.ts:
import { Component, OnInit } from '#angular/core';

Resources